Translator
With the packages\base\Translator class — whose methods are written as static for convenient use without repeating code — you can make the text throughout your website multilingual. To do this, the site's text is stored in separate json files. Using the Translator class, you can reuse the stored phrases across your code as many times as you need. When a language code or country code appears in the URL (either as part of the path or as a URL parameter), the framework automatically loads the language file corresponding to that language or country. In addition, when generating URLs, if you use the base\url method, it automatically includes the default language in the URLs.
A sample language file:
{
"author": {
"name" : "Jalno contributors",
"website" : "https://jalno.ir/"
},
"rtl": true,
"phrases":{
"title": "Jalno framework docs",
"description": "Powered by <a href=\"{url}\">Jalno</a> , open-license framework"
}
}
Language Configuration
To work with languages, you first need to configure a few settings in the config.php file located at packages/base/libraries/config.
In this file, you can configure the default language, how the language is changed, and whether short language codes are allowed.
Default Language
Using the packages.base.translator.defaultlang option, you can set the site's default language. The value must be a full language code.
If this option is not set, any full language code is accepted.
A full language code consists of a two-letter language code and a two-letter country code, separated by an underscore.
'packages.base.translator.defaultlang' => 'fa_IR' // or en_US
Changing the Language
Using the packages.base.translator.changelang option, you specify how the user selects the language. It can take three values:
| Value | Purpose |
|---|---|
| uri | The language is added at the beginning of the URL. |
| parameter | The language is added at the end of the URL. |
| (empty) | The user cannot change the language directly. |
Example (uri):
/fa/contactus
Example (parameter):
/contactus?lang=fa
Example (empty): the language is not added to the URL.
/contactus
Short Language Codes
The packages.base.translator.changelang.type option lets you use short language codes in the URL. It accepts the values short and complete.
Example
'packages.base.translator.changelang.type' => 'short' // /fa/contactus
'packages.base.translator.changelang.type' => 'complete' // /fa_IR/contactus
Registering Language Files
Before a language file can be used, it must be registered with the framework, specifying which language code each file belongs to.
If the language file is used in a frontend (user interface), it is registered in the theme.json file; otherwise, it is registered in the package.json file.
{
"languages": {
"fa_IR": "langs/fa_IR.json"
}
}
{
"name": "frontname",
"title": "Site Frontend",
"version": "1.0.0",
"languages": {
"fa_IR": "langs/fa_IR.json"
}
}
In both files, the following code block defines the languages of that template or package:
"languages": {
"fa_IR" : "langs/fa_IR.json"
}
And if you have more than one language:
"languages": {
"fa_IR" : "langs/fa_IR.json",
"en_US" : "langs/en_US.json"
}
Allowed Language Codes
In the Translator class, the allowed language codes are predefined as two-letter codes in a static property named allowlangs.
Translator::$allowlangs;
Allowed Country Codes
The allowed country codes are stored as two-letter codes in an array in a property named countries.
Translator::$countries;
Setting the Language
If you want to set or change the language of a page, you can use the setLang method of the Translator class. This method takes a full language code as its parameter. If the specified language code is not among the allowed language codes, it stops execution by throwing a packages\base\Translator\InvalidLangCode exception.
A full language code consists of a two-letter language code and a two-letter country code, separated by an underscore.
Example:
namespace packages\my_package\controllers;
use packages\base\{Response, Controller, View, Translator};
use themes\my_theme\views;
class Main extends controller {
public function index(): Response {
Translator::setLang("en_US");
$view = View::byName(views\Home::class);
$this->response->setView($view);
return $this->response;
}
}
Because of the spelling differences between various accents and dialects (such as British and American, or Iranian Persian and Tajik Persian), Jalno lets you define a separate language file for each — for example, en_GB and en_US.
Using Translations
To use translations within your code, you should use the trans method. Its first parameter is the key name, and its second parameter receives an array of key-value pairs.
If a phrase contains a placeholder, this method looks it up by key in the array passed as the second parameter and replaces the placeholder in the phrase with its value.
The second parameter allows us to build the desired text dynamically.
Translator::trans(string $name, array $params = []): string;
To make programming easier and faster, the t(string $name, array $params = []): string function is defined in the root namespace and does exactly the same job as the trans() method.
This function can be used in all files (controller, view, html, process).
It also does not need to be imported with use and can be called from anywhere in your code.
{
"rtl": true,
"phrases":{
"title": "جالنو",
"description": "قدرت گرفته از <a href=\"{url}\"> جالنو </a>" ,
"support.period": "پشتیبانی رسمی تا {month} ماه",
"log.invoice.edit": "کاربر <span class=\"tooltips\" title=\"#{user_id}\">{user_name}</span> صورتحساب را ویرایش کرد ",
}
}
{
"phrases":{
"title": "Jalno",
"description": "Powered by <a href=\"{url}\"> Jalno </a>",
"support.period": "Official support for {month} months",
"log.invoice.edit": "<span class=\"tooltips\" title=\"#{user_id}\">{user_name}</span> just edited the invoice.",
}
}
Example 1:
URL: test.com/fa
<?php
use packages\base\Translator;
?>
<!DOCTYPE html>
<html>
<head>
<title><?php echo Translator::trans("title"); ?></title>
/*
output:
<title>جالنو</title>
*/
</head>
</html>
Example 2:
URL: test.com/en
<!DOCTYPE html>
<html>
<head>
<title><?php echo t("title"); ?></title>
/*
output:
<title>Jalno</title>
*/
</head>
</html>
Example 3:
URL: test.com/en
<!DOCTYPE html>
<html>
<body>
<?php echo t("support.period", array("month" => 6)); ?>
/*
Output:
Official support for 6 months
*/
</body>
</html>
Example 4:
URL: test.com/fa
<?php
use packages\base;
?>
<!DOCTYPE html>
<html>
<body>
<?php echo t("description", array("url" => base\url())); ?>
/*
Output:
قدرت گرفته از <a href="/"> جالنو </a>
*/
</body>
</html>
Example 5: Using the translator in a Controller
namespace packages\package_name\controllers;
use packages\base\{Response, Controller, Date};
use packages\package_name\{Log, User, Invoice};
class Invoice extends Controller {
public function update($data): Response {
$user = (new User)->byId($data["userId"]);
$invoice = (new Invoice)->byId($data["invoiceId"]);
if($user and $invoice) {
$log = new Log();
$log->user = t("log.invoice.edit", ['user_name' => $user->getFullName(), 'user_id' => $user->id]);
$log->date = Date::time();
$log->invoice = $invoice->id;
$log->save();
}
return $this->response;
}
}
To see more examples of using the translator in controllers, refer to the Users management controller in Userpanel file.
Example 6: Using the translator in a View
namespace themes\clipone\views;
use packages\userpanel\Authorization;
use themes\clipone\Navigation;
use function packages\userpanel\url;
class ContactUs extends \packages\userpanel\View {
public static function onSourceLoad() {
if (!Authorization::is_accessed("contact_us")) {
return;
}
$contactUs = Navigation::getByName("contact-us");
if ($contactUs) {
return;
}
$contactUs = new Navigation\MenuItem("contact-us");
$contactUs->setTitle(t("contactus"));
$contactUs->setIcon('fa fa-envelope-open');
$contactUs->setURL(url('contact-us'));
$contactUs->setPriority(400);
Navigation::addItem($contactUs);
}
public function __beforeLoad() {
$this->setTitle(array(
t("contactus"),
t("comments")
));
$this->addBodyClass('contact-us');
Navigation::active("contact-us");
}
}
Example 7: Using the translator in a process
namespace packages\package_name\processes;
use packages\base\Process;
use packages\package_name\Classroom as ClassroomDB;
class Classroom extends Process {
public function insert($data) {
$classroom = new ClassroomDB();
$classroom->title = t("class.title", array("title" => $data["title"], "group" => $data["group"]));
$classroom->teacher = $data["teacher"];
$classroom->save();
}
}
/* Sample language file
{
"phrases":{
"class.title": "کلاس {title} در گروه {group}"
}
}
*/
To see more examples of using the translator in processes, refer to this file.