W3Cschool
恭喜您成為首批注冊(cè)用戶(hù)
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
CodeIgniter 提供了一系列幫助你處理多語(yǔ)言環(huán)境下將應(yīng)用本土化的工具。盡管一個(gè)應(yīng)用完全地本土化是一個(gè)復(fù)雜的問(wèn)題,在你的應(yīng)用中將一些字符串根據(jù)不同的語(yǔ)言進(jìn)行替換,是相當(dāng)簡(jiǎn)單的。
語(yǔ)言字符串存儲(chǔ)于 app/Language 目錄下,其下的每個(gè)子目錄都代表著一種所支持的語(yǔ)言:
/app
/Language
/en
app.php
/fr
app.php
重要
地區(qū)的識(shí)別僅對(duì)于使用了 IncomingRequest 類(lèi)的基于 web 的請(qǐng)求起效,命令行請(qǐng)求無(wú)法使用這些功能。
每個(gè)站點(diǎn)都擁有默認(rèn)的語(yǔ)言/地區(qū)屬性,可以通過(guò) Config/App.php 進(jìn)行設(shè)置:
public $defaultLocale = 'en';
該變量的值,可以是任何字符串值,用于你的應(yīng)用程序處理文本字符串和其他格式用。 我們推薦使用 BCP 47 類(lèi)型的語(yǔ)言代號(hào)。該說(shuō)明中,語(yǔ)言編碼是例如用于美國(guó)英語(yǔ)的 en-US 或者是用于法國(guó)法語(yǔ)的 fr-FR 的格式。 或者也可以參照 W3C’s site 以獲取可讀性更高的說(shuō)明。
如果不能找到絕對(duì)匹配的語(yǔ)言代碼時(shí),該系統(tǒng)將足夠靈活地使用更為泛化的語(yǔ)言代碼。 如果地區(qū)代碼被設(shè)為 en-US ,而只有 en 語(yǔ)言的語(yǔ)言文件,那么因?yàn)闆](méi)有更為精確地匹配 en-US 的語(yǔ)言,我們就會(huì)使用這些語(yǔ)言文件。 但是如果有一個(gè)語(yǔ)言文件目錄 app/Language/en-US 存在的話,該目錄里的語(yǔ)言文件就會(huì)被首先使用。
我們有兩種方式用于在請(qǐng)求中識(shí)別正確的地區(qū)。第一種方式是”設(shè)后即忘”的方式,并會(huì)自動(dòng)執(zhí)行 內(nèi)容協(xié)商 以決定使用正確的地區(qū)。 第二種方式使得你可以在路由中給定一個(gè)特定的分段并用于設(shè)置地區(qū)。
你可以通過(guò)在 Config/App
中設(shè)置兩個(gè)額外的參數(shù)來(lái)自動(dòng)開(kāi)啟內(nèi)容協(xié)商。 第一個(gè)參數(shù)用于告訴 Request
類(lèi)我們需要開(kāi)啟內(nèi)容協(xié)商,因此只要將其設(shè)為 true 即可:
public $negotiateLocale = true;
當(dāng)該參數(shù)啟用時(shí),系統(tǒng)會(huì)自動(dòng)根據(jù)你在 $suppoertLocales
中定義的語(yǔ)言數(shù)組來(lái)協(xié)商使用正確的語(yǔ)言。 如果在你提供的語(yǔ)言和所請(qǐng)求的語(yǔ)言中中匹配不到的話,該數(shù)組的第一個(gè)成員就會(huì)被使用。在下例中,在不匹配時(shí), en 地區(qū)就會(huì)被使用:
public $supportedLocales = ['en', 'es', 'fr-FR'];
第二種方法是用一個(gè)自定義的通配符來(lái)檢測(cè)所需要的地區(qū),并將其用于當(dāng)前請(qǐng)求中。在你的路由中,通配符 {locale}}
可以被替換為一個(gè)路由分段。 如果該分段存在的話,所匹配到的路由分段就是你的地區(qū):
$routes->get('{locale}/books', 'App\Books::index');
在本例中,如果用戶(hù)嘗試訪問(wèn) http://example.com/fr/books
,地區(qū)就會(huì)被設(shè)置為 fr
,并假設(shè)這是一個(gè)合理的地區(qū)參數(shù)。
注解
如果該路由分段值匹配不到 App 配置文件中合理的地區(qū)值的話,就會(huì)用默認(rèn)的地區(qū)來(lái)代替。
當(dāng)前地區(qū)默認(rèn)從 IncomingRequest 實(shí)例中獲取,通過(guò) getLocale()
方法。 如果你的控制器繼承了 CodeIgniter\Controller
,以上操作也可以通過(guò) $this->request
來(lái)實(shí)現(xiàn):
<?php namespace App\Controllers;
class UserController extends \CodeIgniter\Controller
{
public function index()
{
$locale = $this->request->getLocale();
}
}
或者你也可以用 服務(wù)類(lèi) 來(lái)獲取當(dāng)前的請(qǐng)求:
$locale = service('request')->getLocale();
語(yǔ)言沒(méi)有所需的任何特定命名約定。 該文件應(yīng)在邏輯上進(jìn)行命名,以描述其保存的內(nèi)容的類(lèi)型。 例如,假設(shè)您要?jiǎng)?chuàng)建一個(gè)包含錯(cuò)誤消息的文件。 您可以簡(jiǎn)單地命名為: Errors.php 。
在文件內(nèi),您將返回一個(gè)數(shù)組,其中數(shù)組中的每個(gè)元素都有一個(gè)鍵和要返回的字符串:
'language_key' => 'The actual message to be shown.'
注解
最好對(duì)給定文件中的所有郵件使用通用前綴,以免與其他文件中名稱(chēng)相似的郵件發(fā)生沖突。 例如,如果您要?jiǎng)?chuàng)建錯(cuò)誤消息,則可以在它們前面加上error_
return [
'errorEmailMissing' => 'You must submit an email address',
'errorURLMissing' => 'You must submit a URL',
'errorUsernameMissing' => 'You must submit a username',
];
你可以使用 lang()
輔助函數(shù)從所有語(yǔ)言文件中獲取文本值,通過(guò)將文件名和語(yǔ)言鍵作為第一個(gè)參數(shù),以點(diǎn)號(hào)(.)分隔。 舉例來(lái)說(shuō),從 Errors
語(yǔ)言文件中加載 errorEmailMissing
字符串,你可以如下操作:
echo lang('Errors.errorEmailMissing');
如果所請(qǐng)求的語(yǔ)言鍵對(duì)于當(dāng)前的地區(qū)來(lái)說(shuō)不存在的話,就會(huì)不做修改的返回請(qǐng)求的參數(shù)。在本例中,如果 ‘Errors.errorEmailMissing’ 對(duì)應(yīng)的翻譯不存在的話,就會(huì)直接被返回。
注解
以下函數(shù)需要加載并啟用 intl 擴(kuò)展。如果該擴(kuò)展未加載,則不會(huì)進(jìn)行替換操作。 可參閱 Sitepoint.
你可以在語(yǔ)言字符串中,通過(guò)對(duì) lang()
函數(shù)的第二個(gè)參數(shù)傳遞一個(gè)值數(shù)組來(lái)替代通配符中的內(nèi)容。這一操作對(duì)于簡(jiǎn)單的數(shù)字翻譯和格式化來(lái)說(shuō)非常方便:
// 語(yǔ)言文件, Tests.php:
return [
"apples" => "I have {0, number} apples.",
"men" => "I have {1, number} men out-performed the remaining {0, number}",
"namedApples" => "I have {number_apples, number, integer} apples.",
];
// 輸出 "I have 3 apples."
echo lang('Tests.apples', [ 3 ]);
通配符中的第一項(xiàng)對(duì)應(yīng)著數(shù)組的索引下標(biāo)(如果該下標(biāo)是數(shù)字格式的話):
// 輸出 "The top 23 men out-performed the remaining 20"
echo lang('Tests.men', [20, 23]);
如果希望的話,你也可以使用命名數(shù)組來(lái)更為直接地傳遞參數(shù):
// 顯示 "I have 3 apples."
echo lang("Tests.namedApples", ['number_apples' => 3]);
顯然你可以實(shí)現(xiàn)比起數(shù)字替換更為高級(jí)的功能。根據(jù)標(biāo)準(zhǔn)庫(kù) official ICU docs 所示,以下類(lèi)型的數(shù)據(jù)可被替換:
Here are a few examples:
// The language file, Tests.php
return [
'shortTime' => 'The time is now {0, time, short}.',
'mediumTime' => 'The time is now {0, time, medium}.',
'longTime' => 'The time is now {0, time, long}.',
'fullTime' => 'The time is now {0, time, full}.',
'shortDate' => 'The date is now {0, date, short}.',
'mediumDate' => 'The date is now {0, date, medium}.',
'longDate' => 'The date is now {0, date, long}.',
'fullDate' => 'The date is now {0, date, full}.',
'spelledOut' => '34 is {0, spellout}',
'ordinal' => 'The ordinal is {0, ordinal}',
'duration' => 'It has been {0, duration}',
];
// Displays "The time is now 11:18 PM"
echo lang('Tests.shortTime', [time()]);
// Displays "The time is now 11:18:50 PM"
echo lang('Tests.mediumTime', [time()]);
// Displays "The time is now 11:19:09 PM CDT"
echo lang('Tests.longTime', [time()]);
// Displays "The time is now 11:19:26 PM Central Daylight Time"
echo lang('Tests.fullTime', [time()]);
// Displays "The date is now 8/14/16"
echo lang('Tests.shortDate', [time()]);
// Displays "The date is now Aug 14, 2016"
echo lang('Tests.mediumDate', [time()]);
// Displays "The date is now August 14, 2016"
echo lang('Tests.longDate', [time()]);
// Displays "The date is now Sunday, August 14, 2016"
echo lang('Tests.fullDate', [time()]);
// Displays "34 is thirty-four"
echo lang('Tests.spelledOut', [34]);
// Displays "It has been 408,676:24:35"
echo lang('Tests.ordinal', [time()]);
你需要閱讀 MessageFormatter 類(lèi)以及 ICU 編碼格式以充分使用這一功能的特性,例如執(zhí)行條件替換,多元素替換等。以上兩者的鏈接都在上文中有所提及,希望可以可以幫助你充分利用這一特性。
為了在替換參數(shù)時(shí)顯式調(diào)用一個(gè)不同的地區(qū),你可以通過(guò)將地區(qū)作為 lang()
方法的第三個(gè)參數(shù)來(lái)實(shí)現(xiàn):
// Displays "The time is now 23:21:28 GMT-5"
echo lang('Test.longTime', [time()], 'ru-RU');
// Displays "£7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-GB');
// Displays "$7.41"
echo lang('{price, number, currency}', ['price' => 7.41], 'en-US');
語(yǔ)言文件可以接受嵌套數(shù)組作為參數(shù),以更為方便地處理列表類(lèi)型的數(shù)據(jù)等:
// Language/en/Fruit.php
return [
'list' => [
'Apples',
'Bananas',
'Grapes',
'Lemons',
'Oranges',
'Strawberries'
]
];
// Displays "Apples, Bananas, Grapes, Lemons, Oranges, Strawberries"
echo implode(', ', lang('Fruit.list'));
如果對(duì)于一個(gè)給定的地區(qū),你有多種語(yǔ)言文件類(lèi)型,例如對(duì)于 Language/en.php
,你可以通過(guò)為這一地區(qū)增加一個(gè)語(yǔ)言變量,例如 Language/en-US/app.php
你唯一需要為這些信息提供的就是它們?cè)诓煌貐^(qū)里的值。如果對(duì)應(yīng)的信息翻譯不存在的話,就會(huì)從主地區(qū)設(shè)置中獲取并賦值。
本土化功能可以將所有翻譯信息回滾為英語(yǔ),以防止在新的信息增加到框架中時(shí),你沒(méi)辦法為所在地區(qū)實(shí)現(xiàn)翻譯。
因此,如果你在使用地區(qū) fr-CA
,那么翻譯信息會(huì)首先從 Language/fr/CA
中搜索,然后在 Language/fr
,最后在 Language/en
中。
在我們的 倉(cāng)庫(kù) .中,有一份”正式的”翻譯集
你可以下載該倉(cāng)庫(kù)并復(fù)制其中的 Language
目錄到你的 app
中。因?yàn)?App
命名空間映射到了你的 app
目錄,對(duì)應(yīng)的翻譯就會(huì)被自動(dòng)使用。
不過(guò)更好的使用方式是在你的項(xiàng)目中使用 composer require codeigniter4/translations
,因?yàn)榉g目錄自動(dòng)映射之后,這樣被翻譯過(guò)的信息就會(huì)自動(dòng)被使用。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: