我正在尝试建立一种方法来允许成员将字符串翻译成其他语言。你可以在这里看到一个例子: 翻译测试
有人建议我使用 php 的原生 gettext()函数,而不是我已经用来加载语言文件的函数,它是这样的:
function loadLanguageFile($language, $file) {
$temp = array();
$data = file_get_contents('./'.$language.'/'.$file.'.'.$language.'.php');
$codes = array (
'/(\'\s*\.\s*\$)(.+?)(\s*\.\s*\')/',
'/(=\s*\$)(.+?)(\s*\.\s*\')/',
'/(\'\s*\.\s*\$)(.+?)(;)/',
'/(\[\')(.+?)(\'\])/',
'/<\?php/s', '/\?>/s', '/<\?/s'
);
$html = array (
'{$2}',
'= \'{$2}',
'{$2}\';',
'[$2]',
'',
);
// Since we don't have the values for the vars.
$data = preg_replace($codes, $html, $data);
// We must change this because they are global.
$data = str_replace('$txt', '$langEditor_txt', $data);
$data = str_replace('$helptxt', '$langEditor_helptxt', $data);
eval($data);
if (isset($langEditor_txt)) {
$temp['txt'] = $langEditor_txt;
unset($GLOBALS['langEditor_txt']);
}
if (isset($langEditor_helptxt)) {
$temp['helptxt'] = $langEditor_helptxt;
unset($GLOBALS['langEditor_helptxt']);
}
return $temp;
}
字符串包含在一个名为如下的文件中:
ManageDPModules.english.php
DreamPortal.english.php
当在任何 php 编辑器中打开时,这些文件可能如下
所示,并且可以包含许多这样的 $txt 变量:
<?php
// Dream Portal (c) 2009-2010 Dream Portal Team
// DreamPortal.english.php; @1.1
global $scripturl, $context;
// General Strings
$txt['forum'] = 'Forum';
$txt['dream_portal'] = 'Dream Portal';
$txt['dp_core_modules'] = 'Collapse or Expand this Module';
$txt['dp_who_forum'] = 'Viewing the forum index of <a href="' . $scripturl . '?action=forum">' . $context['forum_name'] . '</a>.';
$txt['dp_who_portal'] = 'Viewing the portal index of <a href="' . $scripturl . '">' . $context['forum_name'] . '</a>.';
$txt['dp_who_page'] = 'Viewing the page "<a href="' . $scripturl . '?page=%1$s">%2$s</a>".';
?>
我正在使用以下函数来保存翻译:
function langSave($lang, $file) {
// We just don't get values from the form, they have to exist in the english files to be taken seriously.
$default = loadLanguageFile('english', $file);
if ($default['txt']) {
foreach ($default['txt'] as $key=>$string) {
if (isset($_REQUEST['txt'.$key]) && str_replace(' ', '', $_REQUEST['txt'.$key]) != '') {
$data.='$txt[\''.$key.'\'] = \''.str_replace("'", "\'", $_REQUEST['txt'.$key]).'\';'."\n";
}
}
}
if ($default['helptxt']) {
foreach ($default['helptxt'] as $key=>$string) {
if (isset($_REQUEST['helptxt'.$key]) && str_replace(' ', '', $_REQUEST['helptxt'.$key]) != '') {
$data.='$helptxt[\''.$key.'\'] = \''.str_replace("'", "\'", $_REQUEST['helptxt'.$key]).'\';'."\n";
}
}
}
if (isset($data)) {
$codes = array (// '' . $test . '
'/(\{)(.+?)(\})/',
'/(\'\' \. \$)(.+?)( \. \')/',
'/(\' \. \$)(.+?)( \. \'\')/',
'/(\[\')(.+?)(\'\])/',
'/(\[)(.+?)(\])/',
);
$html = array (
'\' . \$$2 . \'',
'\$$2 . \'',
'\' . \$$2',
'[$2]',
'[\'$2\']',
);
// Convert the data back to normal.
$data = preg_replace($codes, $html, $data);
$data = '<?php'."\n".$data.'?>';
file_put_contents('./'.$lang.'/'.$file.'.'.$lang.'.php', $data);
}
languageHome();
}
语言函数:
function languageHome() {
$languages = loadLanguageList();
echo '
Language List
<table>';
foreach ($languages as $language) {
echo '
<tr>
<td>
'.$language.'
</td>
<td>
<a href="index.php?op=langView&lang='.$language.'">View</a>
</td>
</tr>';
}
echo '
</table>';
}
我看不出 gettext 将如何提供帮助。没有办法在每次不重新启动服务器的情况下更新文本目录。也许有人可以为我创建一个演示?
另外,希望它支持 UTF-8。数据应该一致。
那么这个实现有什么问题吗?为什么要使用gettext?如何使用它来改进翻译以同时适用于 UTF-8 和非 UTF-8 语言字符串,以便可以翻译。
编辑:
请注意,这些文件最终需要重命名为:ManageDPModules.[语言].php
、DreamPortal.[语言].php
等,依序排列让翻译发挥作用。那么,目录在这方面如何帮助我呢?如果您想查看可能的最终结果翻译,您可以下载位于 此处并打开 .german.php 语言文件,以查看成员逐个文件提交语言后它应该是什么样子。请注意,其中一些包具有 UTF-8 字符串,有些则没有。软件包的文件名可以让您知道这一点。如果我也可以让它支持 UTF-8 那就太好了,但这不是必需的。请注意,我并不是想在这里创建完整的包。我只想创建 languagefile.[language].php ,其中包含所有翻译后的字符串(我的代码已经这样做了)。
好的,我将为此提供整个 index.php 文件,以便您在进行翻译时可以清楚地看到它的作用。这是 index.php 文件为此,您需要一些英语文件: DreamPortal.english.php, ManageDPModules.english.php 和 DreamHelp.english-utf8.php。现在,为了看到这一点,您需要上传到服务器index.php,在index.php所在的位置创建几个文件夹,调用1 english,并在其中为您想要的每种其他语言创建一个文件夹(我做了2文件夹(西班牙语和法语),然后将 3 种语言文件上传到英语文件夹中。在浏览器中运行index.php,您将看到它正在运行。
现在,我如何使用同样的方法将 gettext 用于目录。我需要启用文件的在线翻译。我需要以与 .english.php 文件相同的风格创建翻译的 PHP 文件,其前缀与 .english.php
之前相同,并且我需要更改文件名中的语言为文件夹名称定义的相同语言。在线翻译是唯一可用的方法。译者只需专注于翻译字符串。他们不应该专注于安装程序、打包、重命名文件等等。这使得这个过程尽可能轻松,允许它在线完成。我知道有一种方法可以做到这一点,甚至可以支持 UTF-8。但我正在使用我目前知道的最好方法。但你们中的很多人在这类事情上比我聪明得多,所以我向你们寻求帮助。
有没有人可以告诉我更好的方法?有一个像我在这个问题中给你的例子吗?
我需要允许翻译人员在线完成翻译,并且还希望它支持 UTF-8 文件以及非 UTF-8 文件。我喜欢为上面提供的链接(翻译测试),以便翻译人员可以在线进行翻译,而无需不用担心其他事情,它会自动创建所需的文件。这与该语言的英文文件名相同,在第一个 .(点)之后带有文件夹名称(代表该语言),并且需要具有扩展名 .php(就像在我当前正在使用的代码)。所以基本上,我需要对当前的 index.php 进行调整,以支持所有或大多数语言的 UTF-8 和非 UTF-8,并被告知使用 gettext() 和目录文件将对此有所帮助。
寻找我当前的 index.php 的修改版本以使用 gettext() ,以支持大多数(如果不是全部)语言和翻译。我对 preg_replace 进行的正则表达式并不完全令人满意,因为在保存/提交翻译时,它似乎在双引号前面放置了一个正斜杠。因此也许还需要对 preg_replace 进行改进。
顺便说一句,我提供了一个带有实际代码的完整示例。我希望有人可以使用我提供的代码来更改此示例,以使用 GETTEXT 代替并支持 UTF-8。或者实际上提供一个实际的方法让我自己做这件事。不是寻找一堆我自己可以找到的链接!
谢谢你!
I am trying to set up a way to allow members to translate strings into other languages. You can see an example here: TRANSLATIONS TEST
Someone recommended that I use php's native gettext() function for this, instead of what I am already using to load the language files, which is this:
function loadLanguageFile($language, $file) {
$temp = array();
$data = file_get_contents('./'.$language.'/'.$file.'.'.$language.'.php');
$codes = array (
'/(\'\s*\.\s*\$)(.+?)(\s*\.\s*\')/',
'/(=\s*\$)(.+?)(\s*\.\s*\')/',
'/(\'\s*\.\s*\$)(.+?)(;)/',
'/(\[\')(.+?)(\'\])/',
'/<\?php/s', '/\?>/s', '/<\?/s'
);
$html = array (
'{$2}',
'= \'{$2}',
'{$2}\';',
'[$2]',
'',
);
// Since we don't have the values for the vars.
$data = preg_replace($codes, $html, $data);
// We must change this because they are global.
$data = str_replace('$txt', '$langEditor_txt', $data);
$data = str_replace('$helptxt', '$langEditor_helptxt', $data);
eval($data);
if (isset($langEditor_txt)) {
$temp['txt'] = $langEditor_txt;
unset($GLOBALS['langEditor_txt']);
}
if (isset($langEditor_helptxt)) {
$temp['helptxt'] = $langEditor_helptxt;
unset($GLOBALS['langEditor_helptxt']);
}
return $temp;
}
The strings are contained within a file that is named like so:
ManageDPModules.english.php
DreamPortal.english.php
etc.
These files can look like the following, when opened in any php editor, and can have many of these $txt variables:
<?php
// Dream Portal (c) 2009-2010 Dream Portal Team
// DreamPortal.english.php; @1.1
global $scripturl, $context;
// General Strings
$txt['forum'] = 'Forum';
$txt['dream_portal'] = 'Dream Portal';
$txt['dp_core_modules'] = 'Collapse or Expand this Module';
$txt['dp_who_forum'] = 'Viewing the forum index of <a href="' . $scripturl . '?action=forum">' . $context['forum_name'] . '</a>.';
$txt['dp_who_portal'] = 'Viewing the portal index of <a href="' . $scripturl . '">' . $context['forum_name'] . '</a>.';
$txt['dp_who_page'] = 'Viewing the page "<a href="' . $scripturl . '?page=%1$s">%2$s</a>".';
?>
I am using the following function to save the translations:
function langSave($lang, $file) {
// We just don't get values from the form, they have to exist in the english files to be taken seriously.
$default = loadLanguageFile('english', $file);
if ($default['txt']) {
foreach ($default['txt'] as $key=>$string) {
if (isset($_REQUEST['txt'.$key]) && str_replace(' ', '', $_REQUEST['txt'.$key]) != '') {
$data.='$txt[\''.$key.'\'] = \''.str_replace("'", "\'", $_REQUEST['txt'.$key]).'\';'."\n";
}
}
}
if ($default['helptxt']) {
foreach ($default['helptxt'] as $key=>$string) {
if (isset($_REQUEST['helptxt'.$key]) && str_replace(' ', '', $_REQUEST['helptxt'.$key]) != '') {
$data.='$helptxt[\''.$key.'\'] = \''.str_replace("'", "\'", $_REQUEST['helptxt'.$key]).'\';'."\n";
}
}
}
if (isset($data)) {
$codes = array (// '' . $test . '
'/(\{)(.+?)(\})/',
'/(\'\' \. \$)(.+?)( \. \')/',
'/(\' \. \$)(.+?)( \. \'\')/',
'/(\[\')(.+?)(\'\])/',
'/(\[)(.+?)(\])/',
);
$html = array (
'\' . \$2 . \'',
'\$2 . \'',
'\' . \$2',
'[$2]',
'[\'$2\']',
);
// Convert the data back to normal.
$data = preg_replace($codes, $html, $data);
$data = '<?php'."\n".$data.'?>';
file_put_contents('./'.$lang.'/'.$file.'.'.$lang.'.php', $data);
}
languageHome();
}
Language function:
function languageHome() {
$languages = loadLanguageList();
echo '
Language List
<table>';
foreach ($languages as $language) {
echo '
<tr>
<td>
'.$language.'
</td>
<td>
<a href="index.php?op=langView&lang='.$language.'">View</a>
</td>
</tr>';
}
echo '
</table>';
}
I fail to see how gettext will help out. There is no way to update the text catalog without rebooting the server every time. Maybe if someone can create a demo of this for me?
Also, would like it to support UTF-8. The data should be consistent.
So what is wrong with this implementation?? Why use gettext?? How can it be used to improve translations to work for both UTF-8 and non UTF-8 language strings so that it can be translated.?
EDIT:
Please note, the files will eventually need to be renamed to: ManageDPModules.[language].php
, DreamPortal.[language].php
, etc., etc. in order for the translations to work. So, how would catalogs help me in this regard? If you want to see possible END-RESULT Translations, you can download a language package located here and open up the .german.php language files to see what it should look like after the member submits a language on a file by file basis. Noted that some of these packages have UTF-8 strings, and some do not. The filename of the packages let you know this. Would be nice if I can also make it support UTF-8, but it is not a requirement. Please note, I'm not trying to create complete packages here. I just want to create the languagefile.[language].php with all of the translated strings inside of them (which my code already does).
OK, I will provide the ENTIRE index.php file for this so you can see what it does exactly when you do translations. Here is the index.php file for this and you'll need some english language files: DreamPortal.english.php, ManageDPModules.english.php, and DreamHelp.english-utf8.php. Now, in order to see this, you need to upload to a server, index.php, create a few folders where index.php is, call 1 english, and create a folder in there for each additional language you want (I did 2 folders, spanish and french), than upload the 3 language files into the english folder. Run index.php in your browser and you will see it working.
Now, how could I use gettext for catalogs with this SAME approach. I need to enable online translation of files. I need to create PHP files of the translations in the SAME style that the .english.php files are with the same PREFIX that is before .english.php
, and I need to change the language within the filename to the same language defined for the folder name. Online translations is the ONLY method available. Translator's need to focus ONLY on translating the strings. They shouldn't be focusing on installing programs, packaging it up, renaming the files, etc. etc.. This makes this process as painless as possible allowing it to be done online. And I know there is a way to do this, and even for UTF-8 support. But I'm using the best method that I know how at the moment. But so many of you are MUCH smarter at this sort of thing than I am, so I ask for help from you guys.
Is there anyone that can show me a better way? An example like the one that I have given you in this question?
I need to allow translations to be done ONLINE from translators, and would also like it to support UTF-8 files, as well as non UTF-8 files. I like the way I have it setup for the link provided above (TRANSLATIONS TEST) so that translator's can just do the translations online and not have to worry about anything else, and it would automatically create the files needed. Which would be the same as the english filename of the language with the folder name (representing the language) after the first . (dot) and it needs to have the extension .php (like it does in the code I am currently using). So basically, I need an adaption of the current index.php to support UTF-8 and non UTF-8 for all or most languages, and was told that using gettext() and catalog files would help with this.
Looking for a modified version of my current index.php to use gettext() in a way that it will support most, if not all, languages and translations. The REGEX I got going on for preg_replace isn't completely satisfactory because it seems to place a forward slash in front of double quotes when saving/submitting the translations. So perhaps an improvement on the preg_replace would be needed also.
I provided a complete example with ACTUAL CODE bytheway. I'd like for someone to alter this example, with the CODE that I provided to USE GETTEXT instead and support UTF-8. Or actually provide a ACTUAL METHOD for me to do this myself with. Not looking for a bunch of links that I can find on my own!
Thank You!
发布评论
评论(2)
为什么要重新发明轮子?
也许我不明白,但我很确定你想要做的事情以前已经做过了。
只需使用众多现有解决方案之一即可。
在做出决定时,需要考虑以下事项
以下是一些(随机排序):
祝你好运!
更新:谢谢,El Yobo。我已将其标记为社区维基,如果任何人发现其他内容,欢迎编辑或回复其他项目。
Why to re-invent the wheel?
Maybe I don't understand but I'm pretty sure that what you're trying to do has been done before.
Just use one of the many-many existing solutions.
Here are some things to think about, when making your decisions:
Here are some (randomly ordered):
Good luck!
Update: thanks, El Yobo. I've marked this as a community wiki, anyone is welcome to edit or reply with another projects if he find something else.
当您被推荐使用 gettext 时,实际上是建议您使用gettext-类似翻译系统。由于助记符文本索引,您当前的代码很复杂。您在编辑正则表达式时遇到的麻烦是由于摆弄其中的变量引起的。让我提出一些用于过渡目的的替代代码。
gettext 的优点在于它使用非侵入式 API。函数调用
_()
非常简单,可以充分使用,无需添加太多语法或代码膨胀。它比getTextTrans('ABBR_TXT_ID')
更可取。使用这样的助记文本 ID 是一种普遍存在的谬误;因为在实践中并不需要频繁的改写,并且_("Raw english Original text.")
具有相同的目的。但是,由于您已经有了助记键,如果需要更改的内容太多,请保留它们。这只是一个建议。您真正的问题是使用内联 PHP 表达式来构建翻译目标字符串。这就是为什么您的翻译编辑器的正则表达式变得不透明的原因。因此,我强烈建议使用静态字符串并提供占位符。翻译功能应该负责处理它。 (不要担心这里的微优化!) - 我会使用
{$url_xy}
PHP/Smarty 风格的占位符:以及一个查找全局占位符表或参数的翻译函数($context ) 用于替换:
可优化。但通过这种方式,您可以使用翻译数组的静态助记符->文本或英语->文本集。 您仅在文本翻译编辑器表单中使用静态字符串。这些静态字符串按原样显示,您的翻译人员会编辑英文文本,但不会编辑任何
{$placeholders}
。因此,您的翻译功能代码不需要任何复杂的正则表达式(在这种情况下它们没有用)来匹配字符串和内联 PHP 变量。事实上,一个更简单的
include()
和var_export()
组合现在可以取代它:文件处理和其他当然需要定制。但这仍然是一种更简单的方法。
它还将进一步允许您过渡到 gettext 变体之一作为后端。保留您的自定义包装函数
__()
并使用 Zend_Translate 作为后端。这允许您继续使用 .php $txt=array() 翻译文件(或者我认为是这样)或移动到 gettext 样式 .mo/.po 文件。这样做的优点是,与自制解决方案相比,有丰富的工具支持。无论如何,这就是您在主应用程序中使用这些内容的方式:
建议首先从 Short_txt 键转移到英语->外语文本翻译数组,但理论上来自 dvbs 答案的任何后端都适用。现在您已经说过原生 gettext 不适合您(对于非 fastcgi PHP 设置,内存阻力是一个缺点)。但 PHP 的原生 INTL 功能可能对您有帮助。特别是 http://www.php.net/manual/en/class.messageformatter .php 可能比我给你的简单的 {$var} 替换包装器更有用。但我从未使用过它,我认为 Zend_Translate 可能更有用。特别是这些后端中的任何一个都可以为您提供字符集独立性。就我个人而言,无论如何我都会坚持使用 UTF-8。但是,例如,gettext .mo/.po 文件每个都可以有自己的自定义字符集。
When you have been recommended to use gettext, it was actually an advise to use a gettext-like translation system. Your current code is complex because of mnemonic text indicies. And the trouble you got into with the regular expressions for editing is caused by fiddling with variables in there. Let me propose some alternative code for transitional purposes.
The beauty of gettext lies in its use of a non-obtrusive API. The function call
_()
is simple enough to be thoroughly used without adding much syntax or code bloat. It's preferrable to things likegetTextTrans('ABBR_TXT_ID')
. Using such mnemonic text ids is a widespread fallacy; because in practice there aren't frequent rewordings and_("Raw english original text.")
serves the same purpose. However, since you already have mnemonic keys in place, keep them if it's too much to change. This is just a recommendation.Your real problem is the use of inline PHP expressions to build up the translation target strings. They are why the regular expressions for your translation editor became opaque. Therefore I'd highly recommend to use static strings and provide placeholders. The translation function should be tasked with handling it. (Don't worry about microoptimizing here!) - I would use
{$url_xy}
PHP/Smarty-style placeholders for example:And a translation function that looks up a global placeholder table or params ($context) for replacing:
Optimizable. But this way you can use a static mnemonic->text or english->text set of translation arrays. You only use static strings in your text-translation-editor-form thingy. Those static strings are shown as-is, and your translators edit the english text, but not any of the
{$placeholders}
.Hence your code for the translation feature won't need any of the complex regular expressions (in this case they are not useful) to match strings and inline PHP variables. In fact a much simpler
include()
andvar_export()
combination can now take its place:Filehandling and whatnot needs to be customized of course. But still this is a simpler approach.
And it would further allow you to transition to one of the gettext variations as backends. Keep your custom wrapper function
__()
and use e.g. Zend_Translate as backend. This allows you to keep using your .php $txt=array() translation files (or I think so) or move to gettext-style .mo/.po files. The advantage of that being, that there is rich tool support in contrast to homebrew solutions.Anyway this is how you use the stuff in your main application:
Moving from the short_txt keys to english->foreign text translation arrays would be advisable first, but in theory any of the backends from dvbs answer would be applicable. Now you already said that native gettext is not an option for you (for non-fastcgi PHP setups the memory resistance is a drawback). But PHPs native INTL features might be of help to you. In particular http://www.php.net/manual/en/class.messageformatter.php might be more useful than the simple-minded {$var} replacement wrapper I gave you. But I've never used it, and I think Zend_Translate is likely more useful. In particular can any of those backends give you charset independence. Personally I'd just stick to UTF-8, no matter what. But gettext .mo/.po files can each have their own custom charset for example.