【问题标题】:How to deal with javascript internationalization如何处理javascript国际化
【发布时间】:2011-03-23 22:05:02
【问题描述】:
yii 框架中是否有任何机制可以翻译 javascript 源文件中的消息。
例如:
yiic message config-message.php
我可以为所有 Yii::t() 生成翻译 .php 文件。
是否可以使用相同的机制生成 .js 文件。目前我正在将我的 javascript json 数据包含在翻译文件返回的表中。
【问题讨论】:
标签:
javascript
internationalization
yii
【解决方案1】:
没有具体的方法来处理这个问题。
例如,您可以使用 'message-id' => 'translation' 生成包含数组的文件并包含正确的文件,然后执行诸如 alert($messages['itemDeleted']) 之类的操作。
另一种方法是查看您的 javascript 并在其上使用 Yii::t() 函数。
【解决方案2】:
这确实是个问题。多语言网站始终是个问题。 YII 解决了 php 代码的问题。但是js代码问题依然存在。
我不是很优雅的解决方案,但它的作品。使用 t() 动态创建控制器/组件并生成带有本地化的 js 代码。
/js/get/?file=some-js-file
在布局中:
当然,每个 JS 都需要重写。如果使用小段代码 (cs()->RegisterScript),我也使用 t()。
【解决方案3】:
另一种解决方案是让 Yii 在 DOM 中包含已翻译的消息,稍后您的 JS 代码将访问这些消息,因此:
- 你不需要重复JS代码。
- 翻译集中在 PHP/Yii 框架中。
【解决方案4】:
我只是偶然发现了这个问题,并且使用控制器动态生成 js 代码不是一种选择,因为您会因为在每个请求上启动一个额外的 PHP 进程而浪费资源。这可能是高流量网站的问题。
所以我实施了一种不同的方法:
在 .js 中,消息存储在变量中,例如
var MyJsClass = {
lang:
{
foo: 'Foo',
bar: 'Bar',
},
doSomething: function()
{
console.log(this.lang.foo);
},
};
如果当前语言与应用程序的源语言不同,则在视图中添加翻译:
<?php
$cs = Yii::app()->clientScript;
$cs->registerScriptFile($this->module->assetsUrl.'/js/myjsclass.js');
if (Yii::app()->sourceLanguage != Yii::app()->language) {
$cs->registerScript('MyScriptID', '
MyJsClass.lang.foo = \''.Yii::t('TranslationCategory', 'Translated Foo').'\';
MyJsClass.lang.bar = \''.Yii::t('TranslationCategory', 'Translated Bar').'\';
');
}
?>
【解决方案6】:
这是我的做法。
我的应用程序的小上下文:
- 可用语言因部分而异,可通过
$availableLanguages 变量获得。
- 我创建了非常小的消息文件,以便能够在没有任何安全问题的情况下公开其中的一些文件。然后,我创建了一个名为
$langFiles 的变量,我可以在控制器中对其进行更改。
use yii\helpers\Json;
use yii\helpers\FileHelper;
$files = FileHelper::findFiles(\Yii::getAlias('@app/messages/'));
$translations = [];
// Loop into all the available languages
foreach($availableLanguages as $lang) {
$translations[$lang] = [];
// Get all the available message files
foreach ($langFiles as $file) {
// Import the php file if it exists
$filePath = \Yii::getAlias("@app/messages/{$lang}/{$file}.php");
$key = "app/{$file}";
$translations[$lang][$key] = file_exists($filePath) ? include($filePath) : [];
// Replace '.' by '_' to use the get method
foreach($translations[$lang][$key] as $msg => $value) {
unset($translations[$lang][$key][$msg]);
$msg = str_replace('.', '_', $msg);
$translations[$lang][$key][$msg] = $value;
}
}
}
?>
<script>
var translations = <?= Json::encode($translations) ?>;
var lang = document.getElementsByTagName('html')[0].getAttribute('lang');
function t(category, message) {
// Get method thats works exactly like lodash
const get = (value, path, defaultValue) => {
return String(path).split('.').reduce((acc, v) => {
try {
acc = acc[v];
if(typeof acc === 'undefined') {
throw "Undefined";
}
} catch (e) {
return defaultValue;
}
return acc;
}, value)
}
// Replace '.' by '_' to use the get method.
var key = message.replace('.', '_');
// If the translation is not found, return the original message
console.log(lang+'.'+category+'.'+key, message);
return get(translations, lang+'.'+category+'.'+key, message);
}
</script>
我现在可以使用与 Yii2 中相同的语法将翻译直接放入我的脚本中。示例:
t('app/quotes', 'Hello World. Captain speaking!')