我的服务器已安装:PHP版本5.6.33-3+ubuntu16.04.1+deb.sury.org+1
启用gettext
扩展名。
我正在尝试构建一个非常常见的简单多语言应用程序,我搜索了很多,包括SO,但没有找到任何可行的解决方案。
这是我的步骤:
1.)检查安装的gettext扩展程序。
2.)设置演示项目
目录结构:
/demo
-- test.php
-- /locale/
----/en_GB/
------/LC_MESSAGES/
-------- test.po
-------- test.mo
----/en_IN/
------/LC_MESSAGES/
-------- test.po
-------- test.mo
3.。检查我的系统中的本地可用
C
C.UTF-8
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8
POSIX
4。)使用两种不同的语言en_GB
& en_IN
5.。)创建应用程序文件test.php
<?php
// select default locale
$locale = 'en_GB.utf8'; // or 'en_GB'
// set locale from url string
$locale = (isset($_GET['locale'])) ? $_GET['locale'] : $locale;
// set lang env
putenv("LANGUAGE=$locale");
//set locale:
setlocale( LC_MESSAGES, $locale);
// my understanding for this, is name of my translation files for application ?
$domain = 'test';
// Sets the path for a domain
bindtextdomain($domain, dirname(__FILE__).'/locale'); // where translation files are
//or this:
//bindtextdomain("*", dirname(__FILE__).'/locale');
// Not sure i need to set codeset or not ?
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
?>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body>
<?php
echo _("hello");
?>
</body>
</html>
6。)为locale/en_GB/LC_MESSAGES/test.po
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2018-02-19 12:16+0530\n"
"PO-Revision-Date: 2018-02-19 12:16+0530\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: en_GB\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7.1\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SearchPath-0: test.php\n"
#: test.php:38
msgid "hello"
msgstr "Hello"
7.。)为locale/en_IN/LC_MESSAGES/test.po
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2018-02-19 12:16+0530\n"
"PO-Revision-Date: 2018-02-19 13:01+0530\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.7.1\n"
"X-Poedit-Basepath: ..\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Last-Translator: \n"
"Language: en_IN\n"
"X-Poedit-SearchPath-0: test.php\n"
#: test.php:38
msgid "hello"
msgstr "Namaste"
我使用poedit编译.mo文件
问题1)我有什么想念的最佳做法吗?
更新:通过将.utf8
置于语言环境字符串之后并重新启动服务器和放大器,我修复了gettext无法解决问题的问题。它消除了我的头痛;)
答案 0 :(得分:1)
您是否忘记了将要使用哪个域作为默认域名?
// Not sure i need to set codeset or not ?
bind_textdomain_codeset($domain, 'UTF-8');
textdomain($domain);
?>
答案 1 :(得分:0)
我的问题是服务器缓存了.mo文件,因此在首次处理时它可以正常工作,但是当mo文件将被更改时,这些更改在应用程序上不可见。 您可以尝试一下
<?php
namespace utils;
class simple_i18n
{
const DIR_LANG = '/LC_MESSAGES/';
const CODESET = 'UTF-8';
private static $domain = null;
private static $locale = 'en_US';
public static function init( $locale, $domain )
{
self::$locale = $locale;
self::$domain = $domain;
self::preparePOMO( self::$domain, self::$locale, self::CODESET, I18N_DIR );
self::activateLocaleSettings();
self::generateNewTextdomain();
}
private static function activateLocaleSettings()
{
putenv( 'LC_ALL=' . self::$locale );
setlocale( LC_ALL, self::$locale );
}
private static function generateNewTextdomain()
{
$textDomain = sprintf( '%s_%s', self::$domain, self::$locale );
// Set base directory for all locales
bindtextdomain( $textDomain, I18N_DIR );
// Set domain codeset (optional)
bind_textdomain_codeset( $textDomain, self::CODESET );
// File: ./locale/de_DE/LC_MESSAGES/domain_de_DE.mo
textdomain( $textDomain );
}
private static function preparePOMO( &$domain, $locale, $codeset, $directory )
{
if ( !is_dir( $directory . '/' . $locale . self::DIR_LANG ) ){
self::$locale = 'en_EN';
return;
}
if ( !( $gestor = opendir( $directory . '/' . $locale . self::DIR_LANG ) ) ) return;
while( false !== ( $entrada = readdir( $gestor ) ) ) :
preg_match( '/\d{14,25}/',$entrada, $matches );
if ( $matches ) :
unlink( $directory . '/' . $locale . self::DIR_LANG . $entrada );
endif;
endwhile;
$auxDom = $domain;
$domain = $domain . date( 'Ymdhisu' );
copy( $directory . '/' . $locale . self::DIR_LANG . $auxDom . '_' . $locale . '.mo', $directory . '/' . $locale . self::DIR_LANG . $domain . '_' . $locale . '.mo' );
}
}
此代码为.mo文件创建一个副本,并防止从服务器缓存(否则必须重新启动服务器)。 使用方法:
include_once '[PATH TO simple_i18n.php file]/simple_i18n.php';
现在,您必须为.po和.mo文件定义目录:
defined( 'I18N_DIR' ) || define( 'I18N_DIR', '[PATH TO LOCALE]/locale' );
$locale = 'en_GB'; //or 'en_IN'
$domain = 'your_domain_name'; //in your case test but you must add 'en_GB' and 'en_IN' as sufix in every directory
\utils\simple_i18n::init( $locale, $domain );
现在您可以使用它了!
<?php echo _( 'hello' );?>
我希望它对您有用!