Home > Backend Development > PHP Tutorial > Managing Gettext Translations on Shared Hosting

Managing Gettext Translations on Shared Hosting

Jennifer Aniston
Release: 2025-02-22 08:51:11
Original
1015 people have browsed it

Managing Gettext Translations on Shared Hosting

Core points

  • Gettext is a popular method for translation management of PHP websites, but it has a significant drawback: Apache caches translations, which means that unless the engine is restarted, updates to the translated files will not be visible. This is especially problematic on shared hosting, as administrator privileges are often not available.
  • Audero Shared Gettext is a PHP library that allows developers to bypass Apache's cache of translations loaded through the gettext() function. The library uses a simple trick to create a mirrored copy of the translation file, tricking Apache into thinking it as a new, irrelevant translation, thus avoiding caching issues.
  • Audero Shared Gettext can be installed via Composer, Git, or downloading archives from the repository. After installation, developers can use Composer's autoloader to load classes dynamically and create SharedGette instances.
  • This library requires PHP 5.3 or higher because it uses a namespace and is released under the CC BY-NC 4.0 license and is available for free. Its two main methods are updateTranslation(), which creates a mirrored copy of the translation file, and deleteOldTranslations(), which deletes all copies in the selected translation folder except the latest mirrored copy.

Many companies will eventually turn their target markets globally. This goal will bring about the need to translate a company website into one or more languages. Even if you don’t work for a large company, you may need to launch new services in your native language (assuming you are not a native English speaker) to target the local market and to the global market in English. As developers, it is not our responsibility to translate text, but to prepare the website to support translation. In PHP, the most popular method is through Gettext. This is a great approach because it allows separation of translation from the application, thus enabling parallelization of the process. The problem is that Apache caches translations, so unless you can restart the engine, any updates to the translation file will not appear. This fact is especially annoying if you work on a shared hosting and don't have administrator privileges. In this article, I will describe this issue in detail and explain the solution I found to avoid this issue.

Note: If you are not familiar with the concepts of I18N, translation and Gettext, I strongly recommend that you read this series before exploring this article further. It will give you more detailed information than the brief overview you find here and help you understand these topics better.

Environmental settings

There are many ways to use translation in PHP. The easiest way I can recall is to have an associative array containing all the translated strings and then use the keys to retrieve the correct string. As you might guess, this solution is not scalable and you should avoid using this solution unless you are working on a very, very small project (maybe no more than 5 lines of code). For serious translations, we can use Gettext. This approach allows us to have different files for each target language, which helps maintain separation between business logic, presentation layer, and translation (which we can think of as an add-on to the presentation layer). With Gettext, we can parallelize the process because when we process certain features of the website, translators can still use software such as Poedit to translate.

Translations should be stored in paths with fixed structures. First, we will have a root folder named according to your preferences (e.g. "languages"). In it, we must create a folder for each target language, whose name must comply with the ISO 3166 standard. Therefore, the valid names for Italian translations can be "it_IT" (Italian Italian), "it_CH" (Italian Swiss), "en_US" (American English), and so on. In a folder with language code, we must have a folder called "LC_MESSAGES", where we will store the translation file.

Poedit analyzes the source code of the website and extracts the string to be translated based on one or more patterns we set in the software. It saves the string in a single file with the extension .po (Portable Object), which the software (or equivalent) compiles into a binary .mo file. The latter is the format we are interested in with PHP's gettext() function. The .mo file is a file we have to place in the "LC_MESSAGES" directory we created earlier.

The sample code using gettext() is as follows (the code has been commented so you can quickly understand its function):

<?php
// 包含翻译文件的根文件夹的名称
$translationsPath = 'languages';
// 要翻译到的语言
$language = 'it_IT';
// 翻译文件的名称(在gettext中称为域)
$domain = 'audero';

// 指示此会话将使用哪种语言
putenv("LANG=" . $language);
setlocale(LC_ALL, $language);

// 设置当前域的路径
bindtextdomain($domain, $translationsPath);
// 指定字符编码
bind_textdomain_codeset($domain, 'UTF-8');

// 选择域
textdomain($domain);

// 调用gettext()函数(它有一个名为_()的别名)
echo gettext("HELLO_WORLD"); // 等效于echo _("HELLO_WORLD");
?>
Copy after login
Copy after login

After saving the previous code in the page and loading it in the browser, if gettext() can find the translation file, you will see the translation you made on the screen.

So far, everything went well. The bad news is that once the translation is loaded, Apache caches it. Therefore, unless we can restart the engine, any updates to the translation file will not be displayed. This is especially annoying if we work on a shared hosting and do not have administrator privileges. How to solve this problem? Audero Shared Gettext comes to rescue!

What is Audero Shared Gettext

Audero Shared Gettext is a PHP library (actually just a class, but let me dream about it) that allows you to bypass the issue of translations loaded through the gettext() function being cached by Apache. This library takes a simple and effective approach, so you will always use the latest translations. Audero Shared Gettext requires PHP 5.3 or higher because it uses namespaces and there is a structure described in the previous section. It has two main methods: updateTranslation() and deleteOldTranslations(). The former is the core of the library and is also the way to implement this technique. But what is this technique? Let's take a look at its code to learn more. To fully understand it, it is worth stressing that the constructor of the class accepts the path to store the translation, the language to be translated to, and the name (domain) of the translated file.

<?php
// 包含翻译文件的根文件夹的名称
$translationsPath = 'languages';
// 要翻译到的语言
$language = 'it_IT';
// 翻译文件的名称(在gettext中称为域)
$domain = 'audero';

// 指示此会话将使用哪种语言
putenv("LANG=" . $language);
setlocale(LC_ALL, $language);

// 设置当前域的路径
bindtextdomain($domain, $translationsPath);
// 指定字符编码
bind_textdomain_codeset($domain, 'UTF-8');

// 选择域
textdomain($domain);

// 调用gettext()函数(它有一个名为_()的别名)
echo gettext("HELLO_WORLD"); // 等效于echo _("HELLO_WORLD");
?>
Copy after login
Copy after login

The first thing this method needs to do is to test whether the original binary translation file (.mo file) exists. If it does not exist, the method throws an exception. It then calculates the full path to the translated file based on the parameters provided to the constructor and the last modified timestamp of the file. After that, it creates a new string that concatenates the original domain with the previously calculated timestamp. Once done, here's the trick, which creates a mirrored copy of the translation file. If a file with such a name already exists, the class is smart enough to avoid this copying. Finally, it returns the new name that will be used in bindtextdomain(), bind_textdomain_codeset(), and textdomain(). Doing so, Apache will see that the translation is like it has nothing to do with the original translation, thus avoiding caching issues. As I said, simple and effective!

"Great Aurelio!", you were thinking, "but then my folders will bloat with these copies." That's right. This is why I created deleteOldTranslations(). It deletes all mirror copies of the selected translation folder except the last one.

Now that you have learned what Audero Shared Gettext is and what it can do for you, let's see how to get it.

Installing Audero Shared Gettext

You can get "Audero Shared Gettext" through Composer, adding the following lines to your composer.json:

/**
 * 创建翻译文件的镜像副本
 *
 * @return string 创建的翻译文件的名称(在gettext中称为域)
 *
 * @throws \Exception 如果找不到翻译文件
 */
public function updateTranslation()
{
    if (!self::translationExists()) {
        throw new \Exception('在给定路径中找不到翻译文件。');
    }
    $originalTranslationPath = $this->getTranslationPath();
    $lastAccess = filemtime($originalTranslationPath);
    $newTranslationPath = str_replace(self::FILE_EXTENSION, $lastAccess . self::FILE_EXTENSION, $originalTranslationPath);

    if(!file_exists($newTranslationPath)) {
            copy($originalTranslationPath, $newTranslationPath);
    }

    return $this->domain . $lastAccess;
}
Copy after login

Then run the installation command to parse and download the dependencies:

"require": {
    "audero/audero-shared-gettext": "1.0.*"
}
Copy after login

Composer will install the library into the vendor/audero directory of your project.

If you don't want to use Composer (you really should), you can get the Audero Shared Gettext through Git by running the following command:

php composer.phar install
Copy after login

The last option you have is to access the repository and download it as an archive.

How to use Audero Shared Gettext

Suppose you get Audero Shared Gettext using Composer, which you can rely on its autoloader to load the class dynamically. Then you have to create a SharedGettex instance and call the method you need. You can use one of the methods mentioned above as shown in the following example.

git clone https://github.com/AurelioDeRosa/Audero-Shared-Gettext.git
Copy after login

Conclusion

This article introduces you to Audero Shared Gettext, a simple library (well... class) that allows you to bypass the issue of translations loaded through the gettext() function being cached by Apache. Audero Shared Gettext has extensive compatibility because it requires you to have at least PHP 5.3 (it has been released for a while) because it uses namespaces. Feel free to use the demos and files contained in the repository, and if you find a problem, submit a Pull Request and question. I have released the Audero Shared Gettext under the CC BY-NC 4.0 license so it is free to use.

Have you encountered this problem? How did you solve it? Don't be shy and post your solution in the comments!

(The following is the FAQ part, which has been pseudo-original based on the original text and the original text is kept in mind)

FAQs (FAQ) on managing Gettext translation on shared hosting

How to install Gettext on my shared hosting?

Installing Gettext on a shared hosting can be a bit tricky, as you may not have root access. However, you can still install it through cPanel or Plesk. In cPanel, you can find the option to enable Gettext under the Select PHP Version section. In Plesk, you can enable it under the "PHP Settings" section. If you cannot find these options, you may need to contact your hosting provider for assistance.

Why does my Gettext translation not work?

Your Gettext translation doesn't work for several reasons. A common problem is that the .mo file is not compiled correctly or the file path is incorrect. Make sure the .mo file is in the correct directory and the file path in the code is correct. Another problem might be that the locale you are using is not supported by the server. You can check this with the locale -a command.

How to debug Gettext translation?

Debugging Gettext translation can be done by checking for errors in .po and .mo files. You can open these files using tools like Poedit and check for any syntax errors. Additionally, you can use the gettext function in your code to check if the translation is being fetched correctly. If the function returns the original string, the translation cannot be found.

Can I use Gettext in WordPress?

Yes, you can use Gettext in WordPress. WordPress uses Gettext as its localization framework. You can use the __() and _e() functions in WordPress to get translations. These functions use Gettext in the background.

How to update my Gettext translation?

You can update your Gettext translation by updating the .po file and then compiling it into a .mo file. A .po file is a plain text file that you can open with any text editor. Once the changes are done, you can use a tool like Poedit to compile the .po file into a .mo file.

Why do I get the "Package php-gettext cannot be found" error?

This error usually occurs when the package is not available in the repository your server is using. You can try to update your package list using the sudo apt-get update command. If the error persists, you may need to add another repository or install the package manually.

How to use Gettext in PHP?

You can use Gettext in PHP by using gettext function. This function takes a string as an argument and returns the translated string. Before you can use this function, you need to set the locale function using the setlocale function and specify the path to the .mo file using the bindtextdomain function.

Can I use Gettext on Ubuntu?

Yes, you can use Gettext on Ubuntu. You can install it using the sudo apt-get install gettext command. After installation, you can use the gettext command in the terminal to handle .po and .mo files.

How to create .po and .mo files?

You can create .po and .mo files using tools like Poedit. This tool allows you to create and edit .po files and automatically compile them into .mo files. You can also create .po files manually using a text editor, but you need tools like Poedit or msgfmt to compile them into .mo files.

What is the difference between.po and .mo files?

.po file is a plain text file containing the original string and its translation. They can be opened and edited using any text editor. On the other hand, the .mo file is a binary file generated from the .po file. They are used by Gettext to get translations at runtime.

The above is the detailed content of Managing Gettext Translations on Shared Hosting. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template