Language: Add sub-languages using gettext for symfony and vue - refs BT#20922

pull/5000/head
christian 2 years ago
parent 6bfe2f3934
commit 2dee11ec95
  1. 324
      public/main/admin/sub_language.php
  2. 189
      public/main/admin/sub_language_add.php
  3. 88
      public/main/admin/sub_language_ajax.inc.php
  4. 28
      public/main/inc/lib/internationalization.lib.php
  5. 503
      public/main/inc/lib/sub_language.class.php
  6. 35
      src/CoreBundle/Command/UpdateVueTranslations.php

@ -1,8 +1,6 @@
<?php <?php
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
exit;
/** /**
* Script for sub-language administration. * Script for sub-language administration.
*/ */
@ -14,43 +12,38 @@ $this_section = SECTION_PLATFORM_ADMIN;
api_protect_admin_script(); api_protect_admin_script();
$htmlHeadXtra[] = '<script> $htmlHeadXtra[] = '<script>
$(function () { $(function () {
$(".save").click(function() { $(".save").on("click", function() {
var button_name=$(this).attr("name"); var $this = $(this);
var button_array=button_name.split("|"); var buttonId = $this.attr("id");
var button_name=button_array[1]; var textareaId = "txtid_" + buttonId.split("_")[1] + "_" + buttonId.split("_")[2];
var file_id=button_array[2]; var content = $("#" + textareaId).val();
var is_variable_language="$"+button_name; var filename = $this.data("filename");
var msgidEncoded = $this.data("msgid");
var is_new_language = $("#txtid_"+file_id+"_"+button_name).val();
if (is_new_language == undefined) { $this.prop("disabled", true).text("'.get_lang('Loading').'...");
is_new_language="_";
} try {
if (is_new_language.length>0 && is_new_language!="_" && file_id!="" && button_name!="") { $.post(
$.ajax({ "' . api_get_path(WEB_CODE_PATH) . 'admin/sub_language_ajax.inc.php",
contentType: "application/x-www-form-urlencoded", {
beforeSend: function(myObject) { content: content,
$("#div_message_information_id").html("<div class=\"alert alert-info\"><img src=\'../inc/lib/javascript/indicator.gif\' /></div>"); filename: filename,
msgidEncoded: msgidEncoded
}, },
type: "POST", function(data) {
url: "../admin/sub_language_ajax.inc.php", if (data.success) {
data: { localStorage.setItem("redirectTo", textareaId);
\'new_language\': is_new_language, window.location.reload(true);
\'variable_language\': is_variable_language,
\'file_id\': file_id,
\'id\': '.intval($_REQUEST['id']).',
\'sub\': '.intval($_REQUEST['sub_language_id']).',
\'sub_language_id\': '.intval($_REQUEST['sub_language_id']).'
},
success: function(datos) {
if (datos == "1") {
$("#div_message_information_id").html(\''.Display::return_message(get_lang('The new word has been added'), 'success').'\');
} else { } else {
$("#div_message_information_id").html("<div class=\"alert alert-warning\">" + datos +"</div>"); alert("Error: " + (data.error || "'.get_lang('Error, try it again').'"));
} $this.prop("disabled", false).text("'.get_lang('Save').'");
} }
}); },
} else { "json"
$("#div_message_information_id").html(\''.Display::return_message(get_lang('The form contains incorrect or incomplete data. Please check your input.'), 'error').'\'); );
} catch (e) {
console.error("Error to check JSON:", e);
$this.prop("disabled", false).text("'.get_lang('Save').'");
} }
}); });
}); });
@ -72,11 +65,6 @@ if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) {
$sub_language_name = SubLanguageManager::get_name_of_language_by_id($_GET['sub_language_id']); $sub_language_name = SubLanguageManager::get_name_of_language_by_id($_GET['sub_language_id']);
$all_data_of_language = SubLanguageManager::get_all_information_of_language($_GET['id']); $all_data_of_language = SubLanguageManager::get_all_information_of_language($_GET['id']);
$all_data_of_sublanguage = SubLanguageManager::get_all_information_of_language($_GET['sub_language_id']); $all_data_of_sublanguage = SubLanguageManager::get_all_information_of_language($_GET['sub_language_id']);
$sub_language_file = api_get_path(SYS_LANG_PATH).$all_data_of_sublanguage['dokeos_folder'];
if (!file_exists($sub_language_file) || !is_writable($sub_language_file)) {
$sublanguage_folder_error = $sub_language_file.' '.get_lang('is not writeable');
}
if (true === SubLanguageManager::check_if_exist_language_by_id($_GET['id'])) { if (true === SubLanguageManager::check_if_exist_language_by_id($_GET['id'])) {
$language_id_exist = true; $language_id_exist = true;
} else { } else {
@ -88,11 +76,6 @@ if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) {
} }
$intro = sprintf(get_lang('Define new terms for sub-language %s by searching some term, then save each translation by clicking the save button. You will then have to switch your own user language to see the new terms appear.'), strtolower($sub_language_name)); $intro = sprintf(get_lang('Define new terms for sub-language %s by searching some term, then save each translation by clicking the save button. You will then have to switch your own user language to see the new terms appear.'), strtolower($sub_language_name));
$path_folder = api_get_path(SYS_LANG_PATH).$all_data_of_language['dokeos_folder'];
if (!is_dir($path_folder) || 0 == strlen($all_data_of_language['dokeos_folder'])) {
api_not_allowed(true);
}
Display :: display_header($language_name); Display :: display_header($language_name);
@ -121,237 +104,61 @@ if (!empty($sublanguage_folder_error)) {
echo '<div id="div_message_information_id">&nbsp;</div>'; echo '<div id="div_message_information_id">&nbsp;</div>';
/** /**
* @param $term The term to search * Searches for a term in language files and returns results.
* @param bool $search_in_variable The search will include the variable definition of the term *
* @param bool $search_in_english The search will include the english language variables * @param string $term The term to search for.
* @param bool $search_in_parent The search will include the parent language variables of the sub language * @param int $subLanguageId The ID of the sub-language to search in.
* @param bool $search_in_sub_language The search will include the sub language variables
* *
* @author Julio Montoya * @author Julio Montoya
* *
* @return array * @return array An array containing search results.
*/
function search_language_term(
$term,
$search_in_variable = true,
$search_in_english = true,
$search_in_parent = true,
$search_in_sub_language = true
) {
//These the $_REQUEST['id'] and the $_REQUEST['sub_language_id'] variables are process in global.inc.php (LOAD LANGUAGE FILES SECTION)
/*
These 4 arrays are set in global.inc.php with the condition that will be load from sub_language.php or sub_language_ajax.inc.php
$english_language_array
$parent_language_array
$sub_language_array
$language_files_to_load
*/ */
global $language_files_to_load, $sub_language_array, $english_language_array, $parent_language_array; function search_language_term($term, $subLanguageId)
$language_files_to_load_keys = array_flip($language_files_to_load); {
$array_to_search = $parent_language_array; $translations = SubLanguageManager::searchTranslations($term, $subLanguageId);
$list_info = []; $listInfo = [];
$term = '/'.Security::remove_XSS(trim($_REQUEST['txt_search_word'])).'/i'; if (!empty($translations)) {
//@todo optimize this foreach $i = 0;
foreach ($language_files_to_load as $lang_file) { foreach ($translations as $trans) {
//searching in parent language of the sub language $keys = array_keys($trans);
if ($search_in_parent) { $firstTranslationKey = $keys[4];
$variables = $parent_language_array[$lang_file]; $secondTranslationKey = $keys[5];
foreach ($variables as $parent_name_variable => $parent_variable_value) { $langFile = "messages.$secondTranslationKey.po";
//arrays are avoided $objText = Display::tag(
if (is_array($parent_variable_value)) {
continue;
}
$founded = false;
// searching the item in the parent tool
if (0 !== preg_match($term, $parent_variable_value)) {
$founded = true;
}
if ($founded) {
//loading variable from the english array
$sub_language_name_variable = isset($sub_language_array[$lang_file][$parent_name_variable])
? $sub_language_array[$lang_file][$parent_name_variable]
: '';
//loading variable from the english array
$english_name_variable = $english_language_array[$lang_file][$parent_name_variable];
//config buttons
/*if (strlen($english_name_variable)>1500) {
$size =20;
} else {
$size =4;
}*/
$obj_text = Display::tag(
'textarea', 'textarea',
$sub_language_name_variable, $trans[$secondTranslationKey],
[ [
'rows' => 10, 'rows' => 10,
'cols' => 40, 'cols' => 40,
'name' => 'txt|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file], 'name' => 'txt|'.$trans['phpVarName'].'|'.$i,
'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$parent_name_variable, 'id' => 'txtid_'.$i.'_'.$trans['phpVarName'],
] ]
); );
$obj_button = Display::button( $objButton = Display::button(
'btn|'.$parent_name_variable.'|'.$language_files_to_load_keys[$lang_file], 'btn|'.$trans['phpVarName'].'|'.$i,
get_lang('Save'), get_lang('Save'),
[ [
'class' => 'save btn btn--plain btn-sm', 'class' => 'save btn btn--plain btn-sm',
'type' => 'button', 'type' => 'button',
'id' => 'btnid_'.$parent_name_variable, 'id' => 'btnid_'.$i.'_'.$trans['phpVarName'],
'data-filename' => $langFile,
'data-msgid' => base64_encode($trans['variable']),
] ]
); );
$listInfo[$i] = [
$list_info[$parent_name_variable] = [ $langFile,
$lang_file.'.inc.php', $trans['variable'],
$parent_name_variable, htmlentities($trans['en']),
htmlentities($english_name_variable), htmlentities($trans[$firstTranslationKey]),
htmlentities($parent_variable_value), $objText,
$obj_text, $objButton,
$obj_button,
]; ];
}
}
}
//search in english
if ($search_in_english || $search_in_variable) {
$variables = $english_language_array[$lang_file];
foreach ($variables as $name_variable => $variable_value) {
if (isset($list_info[$name_variable])) {
continue;
}
if (is_array($variable_value)) {
continue;
}
if (is_array($variable_value)) {
echo $lang_file;
}
$founded = false;
if ($search_in_english && $search_in_variable) {
// searching the item in the parent tool
if (0 !== preg_match($term, $variable_value) || 0 !== preg_match($term, $name_variable)) {
$founded = true;
}
} else {
if ($search_in_english) {
if (0 !== preg_match($term, $variable_value)) {
$founded = true;
}
} else {
if (0 !== preg_match($term, $name_variable)) {
$founded = true;
}
}
}
if ($founded) { $i++;
//loading variable from the english array
$sub_language_name_variable = null;
if (isset($sub_language_array[$lang_file][$name_variable])) {
$sub_language_name_variable = $sub_language_array[$lang_file][$name_variable];
} }
$parent_variable_value = null;
if (isset($parent_language_array[$lang_file][$name_variable])) {
$parent_variable_value = $parent_language_array[$lang_file][$name_variable];
} }
//config buttons
$obj_text = Display::tag(
'textarea',
$sub_language_name_variable,
[
'rows' => 10,
'cols' => 40,
'name' => 'txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable,
]
);
$obj_button = Display::button(
'btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
get_lang('Save'),
[
'class' => 'save btn btn--plain btn-sm',
'type' => 'button',
'id' => 'btnid_'.$name_variable,
]
);
//loading variable from the english array
$english_name_variable = $english_language_array[$lang_file][$name_variable];
$list_info[] = [
$lang_file.'.inc.php',
$name_variable,
htmlentities($english_name_variable),
htmlentities($parent_variable_value),
$obj_text,
$obj_button,
];
}
}
}
// Search in sub language
if ($search_in_sub_language) {
$variables = $sub_language_array[$lang_file];
foreach ($variables as $name_variable => $variable_value) {
if (is_array($parent_variable_value)) {
continue;
}
if (is_array($variable_value)) {
continue;
}
$founded = false;
// searching the item in the parent tool
if (0 !== preg_match($term, $variable_value)) {
$founded = true;
}
if ($founded) {
//loading variable from the english array
$sub_language_name_variable = isset($sub_language_array[$lang_file][$name_variable])
? $sub_language_array[$lang_file][$name_variable]
: '';
$parent_variable_value = isset($parent_language_array[$lang_file][$name_variable])
? $parent_language_array[$lang_file][$name_variable]
: '';
//config buttons
$obj_text = Display::tag(
'textarea',
$sub_language_name_variable,
[
'rows' => 10,
'cols' => 40,
'name' => 'txt|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
'id' => 'txtid_'.$language_files_to_load_keys[$lang_file].'_'.$name_variable,
]
);
$obj_button = Display::button(
'btn|'.$name_variable.'|'.$language_files_to_load_keys[$lang_file],
get_lang('Save'),
[
'class' => 'save btn btn--plain btn-sm',
'type' => 'button',
'id' => 'btnid_'.$name_variable,
]
);
//loading variable from the english array
$english_name_variable = $english_language_array[$lang_file][$name_variable];
$list_info[] = [$lang_file.'.inc.php',
$name_variable,
$english_name_variable,
$parent_variable_value, $obj_text, $obj_button, ];
}
}
}
}
$list_info = array_unique_dimensional($list_info);
return $list_info; return $listInfo;
} }
// Allow see data in sort table // Allow see data in sort table
@ -361,10 +168,7 @@ if (isset($_REQUEST['txt_search_word'])) {
if (strlen(trim($_REQUEST['txt_search_word'])) > 2) { if (strlen(trim($_REQUEST['txt_search_word'])) > 2) {
$list_info = search_language_term( $list_info = search_language_term(
$_REQUEST['txt_search_word'], $_REQUEST['txt_search_word'],
true, $_GET['sub_language_id'],
true,
true,
true
); );
} }
} }

@ -20,149 +20,10 @@ $tool_name = get_lang('Create sub-language');
$interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')]; $interbreadcrumb[] = ['url' => 'index.php', 'name' => get_lang('Administration')];
$interbreadcrumb[] = ['url' => 'languages.php', 'name' => get_lang('Chamilo Portal Languages')]; $interbreadcrumb[] = ['url' => 'languages.php', 'name' => get_lang('Chamilo Portal Languages')];
/**
* Add sub-language.
*
* @deprecated
*
* @param string Original language name (Occitan, Wallon, Vlaams)
* @param string English language name (occitan, wallon, flanders)
* @param string ISO code (fr_FR, ...)
* @param int Whether the sublanguage is published (0=unpublished, 1=published)
* @param int ID del idioma padre
*
* @return false|string New sub language ID or false on error
*/
function add_sub_language($original_name, $english_name, $isocode, $sublanguage_available, $parent_id)
{
$tbl_admin_languages = Database::get_main_table(TABLE_MAIN_LANGUAGE);
$original_name = Database::escape_string($original_name);
$english_name = Database::escape_string($english_name);
$isocode = Database::escape_string($isocode);
$sublanguage_available = Database::escape_string($sublanguage_available);
$parent_id = intval($parent_id);
$sql = 'INSERT INTO '.$tbl_admin_languages.'(original_name,english_name,isocode,dokeos_folder,available,parent_id)
VALUES ("'.$original_name.'","'.$english_name.'","'.$isocode.'","'.$english_name.'","'.$sublanguage_available.'","'.$parent_id.'")';
$res = Database::query($sql);
if (false === $res) {
return false;
}
return Database::insert_id();
}
/**
* Check if language exists.
*
* @param string Original language name (Occitan, Wallon, Vlaams)
* @param string English language name (occitan, wallon, flanders)
* @param string ISO code (fr_FR, ...)
* @param int Whether the sublanguage is published (0=unpublished, 1=published)
*
* @return array Array describing the number of items found that match the
* current language insert attempt (original_name => true,
* english_name => true, isocode => true,
* execute_add => true/false). If execute_add is true, then we
* can proceed.
*
* @todo This function is not transaction-safe and should probably be included
* inside the add_sub_language function.
*/
function check_if_language_exist($original_name, $english_name, $isocode, $sublanguage_available)
{
$tbl_admin_languages = Database::get_main_table(TABLE_MAIN_LANGUAGE);
$sql_original_name = 'SELECT count(*) AS count_original_name FROM '.$tbl_admin_languages.'
WHERE original_name="'.Database::escape_string($original_name).'" ';
$sql_english_name = 'SELECT count(*) AS count_english_name FROM '.$tbl_admin_languages.'
WHERE english_name="'.Database::escape_string($english_name).'" ';
$rs_original_name = Database::query($sql_original_name);
$rs_english_name = Database::query($sql_english_name);
$count_original_name = Database::result($rs_original_name, 0, 'count_original_name');
$count_english_name = Database::result($rs_english_name, 0, 'count_english_name');
$has_error = false;
$message_information = [];
if (1 == $count_original_name) {
$has_error = true;
$message_information['original_name'] = true;
}
if (1 == $count_english_name) {
$has_error = true;
$message_information['english_name'] = true;
}
$iso_list = api_get_platform_isocodes();
$iso_list = array_values($iso_list);
if (!in_array($isocode, $iso_list)) {
$has_error = true;
$message_information['isocode'] = true;
}
if (true === $has_error) {
$message_information['execute_add'] = false;
}
if (false === $has_error) {
$message_information['execute_add'] = true;
}
return $message_information;
}
/**
* Check if language exist, given its ID. This is just a wrapper for the
* SubLanguageManager::check_if_exist_language_by_id() method and should not exist.
*
* @param int Language ID
*
* @return bool
*
* @todo deprecate this function and use the static method directly
*/
function check_if_exist_language_by_id($language_id)
{
return SubLanguageManager::check_if_exist_language_by_id($language_id);
}
/**
* Check if the given language is a parent of any sub-language.
*
* @param int Language ID of the presumed parent
*
* @return bool True if this language has children, false otherwise
*/
function ckeck_if_is_parent_of_sub_language($parent_id)
{
$sql = 'SELECT count(*) AS count FROM language WHERE parent_id= '.intval($parent_id);
$rs = Database::query($sql);
if (Database::num_rows($rs) > 0 && 1 == Database::result($rs, 0, 'count')) {
return true;
} else {
return false;
}
}
/**
* Get all information of sub-language.
*
* @param int Parent language ID
* @param int Child language ID
*
* @return array
*/
function allow_get_all_information_of_sub_language($parent_id, $sub_language_id)
{
return SubLanguageManager::get_all_information_of_sub_language($parent_id, $sub_language_id);
}
/*end declare functions*/
//add data //add data
if (isset($_GET['sub_language_id']) && $_GET['sub_language_id'] == strval(intval($_GET['sub_language_id']))) { if (isset($_GET['sub_language_id']) && $_GET['sub_language_id'] == strval(intval($_GET['sub_language_id']))) {
$language_name = SubLanguageManager::get_name_of_language_by_id($_GET['sub_language_id']); $language_name = SubLanguageManager::get_name_of_language_by_id($_GET['sub_language_id']);
if (true === check_if_exist_language_by_id($_GET['sub_language_id'])) { if (true === SubLanguageManager::languageExistsById($_GET['sub_language_id'])) {
$sub_language_id = $_GET['sub_language_id']; $sub_language_id = $_GET['sub_language_id'];
$sub_language_id_exist = true; $sub_language_id_exist = true;
} else { } else {
@ -174,8 +35,8 @@ $language_name = '';
if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) { if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) {
$language_details = SubLanguageManager::get_all_information_of_language($_GET['id']); $language_details = SubLanguageManager::get_all_information_of_language($_GET['id']);
$language_name = $language_details['original_name']; $language_name = $language_details['original_name'];
if (true === check_if_exist_language_by_id($_GET['id'])) { if (true === SubLanguageManager::languageExistsById($_GET['id'])) {
$parent_id = $_GET['id']; $parent_id = (int) $_GET['id'];
$language_id_exist = true; $language_id_exist = true;
} else { } else {
$language_id_exist = false; $language_id_exist = false;
@ -189,8 +50,8 @@ if (isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) {
if ((isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) && if ((isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) &&
(isset($_GET['sub_language_id']) && $_GET['sub_language_id'] == strval(intval($_GET['sub_language_id']))) (isset($_GET['sub_language_id']) && $_GET['sub_language_id'] == strval(intval($_GET['sub_language_id'])))
) { ) {
if (true === check_if_exist_language_by_id($_GET['id']) && true === check_if_exist_language_by_id($_GET['sub_language_id'])) { if (true === SubLanguageManager::languageExistsById($_GET['id']) && true === SubLanguageManager::languageExistsById($_GET['sub_language_id'])) {
$get_all_information = allow_get_all_information_of_sub_language($_GET['id'], $_GET['sub_language_id']); $get_all_information = SubLanguageManager::getAllInformationOfSubLanguage((int) $_GET['id'], (int) $_GET['sub_language_id']);
$original_name = $get_all_information['original_name']; $original_name = $get_all_information['original_name'];
$english_name = $get_all_information['english_name']; $english_name = $get_all_information['english_name'];
$isocode = $get_all_information['isocode']; $isocode = $get_all_information['isocode'];
@ -199,7 +60,7 @@ if ((isset($_GET['id']) && $_GET['id'] == strval(intval($_GET['id']))) &&
$language_name = get_lang('Create sub-languageForLanguage').' ( '.strtolower($language_name).' )'; $language_name = get_lang('Create sub-languageForLanguage').' ( '.strtolower($language_name).' )';
if (true === ckeck_if_is_parent_of_sub_language($parent_id) && if (true === SubLanguageManager::isParentOfSubLanguage($parent_id) &&
isset($_GET['action']) && 'deletesublanguage' == $_GET['action'] isset($_GET['action']) && 'deletesublanguage' == $_GET['action']
) { ) {
$language_name = get_lang('Delete sub-language'); $language_name = get_lang('Delete sub-language');
@ -214,9 +75,9 @@ if (isset($_POST['SubmitAddNewLanguage'])) {
$english_name = str_replace(' ', '_', $english_name); $english_name = str_replace(' ', '_', $english_name);
$isocode = str_replace(' ', '_', $isocode); $isocode = str_replace(' ', '_', $isocode);
$sublanguage_available = $_POST['sub_language_is_visible']; $sublanguage_available = isset($_POST['sub_language_is_visible']) ? (int) $_POST['sub_language_is_visible'] : 0;
$check_information = []; $check_information = [];
$check_information = check_if_language_exist($original_name, $english_name, $isocode, $sublanguage_available); $check_information = SubLanguageManager::checkIfLanguageExists($original_name, $english_name, $isocode);
foreach ($check_information as $index_information => $value_information) { foreach ($check_information as $index_information => $value_information) {
$allow_insert_info = false; $allow_insert_info = false;
if ('original_name' == $index_information) { if ('original_name' == $index_information) {
@ -248,20 +109,17 @@ if (isset($_POST['SubmitAddNewLanguage'])) {
$isocode = str_replace(' ', '_', $isocode); $isocode = str_replace(' ', '_', $isocode);
$str_info = '<br/>'.get_lang('Original name').' : '.$original_name.'<br/>'.get_lang('English name').' : '.$english_name.'<br/>'.get_lang('Character set').' : '.$isocode; $str_info = '<br/>'.get_lang('Original name').' : '.$original_name.'<br/>'.get_lang('English name').' : '.$english_name.'<br/>'.get_lang('Character set').' : '.$isocode;
$mkdir_result = SubLanguageManager::add_language_directory($english_name); $mkdir_result = SubLanguageManager::addPoFileForSubLanguage($english_name);
if ($mkdir_result) { if ($mkdir_result) {
$sl_id = add_sub_language($original_name, $english_name, $isocode, $sublanguage_available, $parent_id); $sl_id = SubLanguageManager::addSubLanguage($original_name, $english_name, $sublanguage_available, $parent_id);
if (false === $sl_id) { if (false === $sl_id) {
SubLanguageManager::remove_language_directory($english_name); SubLanguageManager::removePoFileForSubLanguage($english_name);
$msg .= Display::return_message(get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), 'error'); $msg .= Display::return_message(get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), 'error');
} else { } else {
Display::addFlash( Display::addFlash(
Display::return_message(get_lang('The new sub-language has been added').$str_info, null, false) Display::return_message(get_lang('The new sub-language has been added').$str_info, null, false)
); );
unset($interbreadcrumb); api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php?sub_language_id='.$sl_id);
$_GET['sub_language_id'] = $_REQUEST['sub_language_id'] = $sl_id;
require 'sub_language.php';
exit();
} }
} else { } else {
$msg .= Display::return_message(get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), 'error'); $msg .= Display::return_message(get_lang('The /main/lang directory, used on this portal to store the languages, is not writable. Please contact your platform administrator and report this message.'), 'error');
@ -276,19 +134,24 @@ if (isset($_POST['SubmitAddNewLanguage'])) {
} }
} }
if (isset($_POST['SubmitAddDeleteLanguage'])) {
$removed = SubLanguageManager::removeSubLanguage($_GET['id'], $_GET['sub_language_id']);
if ($removed) {
Display::addFlash(
Display::return_message(
get_lang(
'The sub language has been removed.'
)
)
);
api_location(api_get_path(WEB_CODE_PATH).'admin/languages.php');
}
}
Display:: display_header($language_name); Display:: display_header($language_name);
echo $msg; echo $msg;
if (isset($_POST['SubmitAddDeleteLanguage'])) {
$rs = SubLanguageManager::remove_sub_language($_GET['id'], $_GET['sub_language_id']);
if (true === $rs) {
echo Display::return_message(get_lang('The sub language has been removed'), 'confirm');
} else {
echo Display::return_message(get_lang('The sub-language has not been removed.'), 'error');
}
}
// ckeck_if_is_parent_of_sub_language($parent_id)===false
if (isset($_GET['action']) && 'definenewsublanguage' == $_GET['action']) { if (isset($_GET['action']) && 'definenewsublanguage' == $_GET['action']) {
$text = $language_name; $text = $language_name;
$form = new FormValidator( $form = new FormValidator(

@ -2,90 +2,20 @@
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
exit;
use Chamilo\CoreBundle\Entity\ExtraField;
/** /**
* Sub language AJAX script to update variables. * Sub language AJAX script to update variables.
*/ */
$this_script = 'sub_language'; require_once __DIR__ . '/../inc/global.inc.php';
require_once __DIR__.'/../inc/global.inc.php';
api_protect_admin_script(); api_protect_admin_script();
$new_language = Security::remove_XSS($_REQUEST['new_language']); if (isset($_POST['content'], $_POST['filename'], $_POST['msgidEncoded'])) {
$language_variable = Security::remove_XSS($_REQUEST['variable_language']); $content = $_POST['content'];
$file_id = intval($_REQUEST['file_id']); $filename = $_POST['filename'];
$msgid = base64_decode($_POST['msgidEncoded']);
if (isset($new_language) && isset($language_variable) && isset($file_id)) {
$file_language = $language_files_to_load[$file_id].'.inc.php';
$id_language = intval($_REQUEST['id']);
$sub_language_id = intval($_REQUEST['sub']);
$all_data_of_language = SubLanguageManager::get_all_information_of_sub_language($id_language, $sub_language_id);
$path_folder = api_get_path(SYS_LANG_PATH).$all_data_of_language['dokeos_folder'].'/'.$file_language;
$all_file_of_directory = SubLanguageManager::get_all_language_variable_in_file($path_folder);
$return_value = SubLanguageManager::add_file_in_language_directory($path_folder);
//update variable language
// Replace double quotes to avoid parse errors
$new_language = str_replace('"', '\"', $new_language);
// Replace new line signs to avoid parse errors - see #6773
$new_language = str_replace("\n", "\\n", $new_language);
$all_file_of_directory[$language_variable] = "\"".$new_language."\";";
$result_array = [];
foreach ($all_file_of_directory as $key_value => $value_info) {
$result_array[$key_value] = SubLanguageManager::write_data_in_file($path_folder, $value_info, $key_value);
}
$variables_with_problems = '';
if (!empty($result_array)) {
foreach ($result_array as $key => $result) {
if (false == $result) {
$variables_with_problems .= $key.' <br />';
}
}
}
if (isset($_REQUEST['redirect'])) {
$message = Display::return_message(get_lang('The new word has been added'), 'success');
if (!empty($variables_with_problems)) {
Display::return_message(
$path_folder.' '.get_lang('is not writeable').'<br /> '.api_ucwords(get_lang('errors found'))
.': <br />'.$variables_with_problems,
'error'
);
}
Display::addFlash($message);
if (isset($_REQUEST['item_type'])) {
$redirectUrl = api_get_path(WEB_CODE_PATH).'admin/extra_fields.php';
switch ($_REQUEST['item_type']) {
case ExtraField::USER_FIELD_TYPE:
header("Location: {$redirectUrl}?type=user");
exit;
case ExtraField::COURSE_FIELD_TYPE:
header("Location: {$redirectUrl}?type=course");
exit;
case ExtraField::SESSION_FIELD_TYPE:
header("Location: {$redirectUrl}?type=session");
exit;
}
}
if (isset($_REQUEST['skill'])) {
header('Location: '.api_get_path(WEB_CODE_PATH).'skills/skill_list.php');
exit;
}
}
if (!empty($variables_with_problems)) { $response = SubLanguageManager::updateOrAddMsgid($filename, $msgid, $content);
echo $path_folder.' '.get_lang('is not writeable').'<br /> '.api_ucwords(get_lang('errors found')).': <br />'.$variables_with_problems; echo json_encode($response);
} else { } else {
echo 1; echo json_encode(["success" => false, "error" => get_lang('POST data missing')]);
}
} }

@ -66,6 +66,8 @@ function get_lang($variable)
return $variable; return $variable;
} }
$defaultLocale = 'en';
$locale = api_get_language_isocode(); $locale = api_get_language_isocode();
$userInfo = api_get_user_info(); $userInfo = api_get_user_info();
if (is_array($userInfo) && !empty($userInfo['language'])) { if (is_array($userInfo) && !empty($userInfo['language'])) {
@ -79,12 +81,36 @@ function get_lang($variable)
// Using symfony // Using symfony
$defaultDomain = 'messages'; $defaultDomain = 'messages';
return $translator->trans( $translated = $translator->trans(
$variable, $variable,
[], [],
$defaultDomain, $defaultDomain,
$locale $locale
); );
if ('true' === api_get_setting('language.allow_use_sub_language')) {
$parentLocale = null;
if ($translated === $variable && $locale !== $defaultLocale) {
$parentLocale = SubLanguageManager::getParentLocale($locale);
$translated = $translator->trans(
$variable,
[],
$defaultDomain,
$parentLocale
);
}
if ($translated === $variable && $parentLocale !== $defaultLocale) {
$translated = $translator->trans(
$variable,
[],
$defaultDomain,
$defaultLocale
);
}
}
return $translated;
} }
/** /**

@ -1,11 +1,17 @@
<?php <?php
/* For licensing terms, see /license.txt */ /* For licensing terms, see /license.txt */
use Chamilo\CoreBundle\Entity\Language;
/** /**
* This is used in some scripts inside tests. * This is used in some scripts inside tests.
*/ */
class SubLanguageManager class SubLanguageManager
{ {
const SUBLANGUAGE_TRANS_PATH = '../var/translations/';
const LANGUAGE_TRANS_PATH = '../translations/';
public function __construct() public function __construct()
{ {
} }
@ -64,32 +70,6 @@ class SubLanguageManager
return $content_dir; return $content_dir;
} }
/**
* Get all information of sub-language.
*
* @param int $parent_id The parent id(Language father id)
* @param int $sub_language_id The sub language id
*
* @return array All information about sub-language
*/
public static function get_all_information_of_sub_language($parent_id, $sub_language_id)
{
$table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
$parent_id = intval($parent_id);
$sub_language_id = intval($sub_language_id);
$sql = "SELECT * FROM $table
WHERE
parent_id = $parent_id AND
id = $sub_language_id";
$rs = Database::query($sql);
$all_information = [];
while ($row = Database::fetch_array($rs, 'ASSOC')) {
$all_information = $row;
}
return $all_information;
}
/** /**
* Get all information of language. * Get all information of language.
* *
@ -183,92 +163,39 @@ class SubLanguageManager
} }
/** /**
* Add directory for sub-language. * Add a .po file for a sub-language using its ISO code.
* *
* @param string $sub_language_dir The sub-language directory ( e.g. 'spanish_corporate' ) * @param string $subLanguageIsoCode The ISO code of the sub-language (e.g., 'es_CO')
* *
* @return bool True on success, false on failure * @return bool True on success, false on failure
*/ */
public static function add_language_directory($sub_language_dir) public static function addPoFileForSubLanguage($subLanguageIsoCode)
{ {
if (empty($sub_language_dir)) { if (empty($subLanguageIsoCode)) {
return false; return false;
} }
$dir = api_get_path(SYS_LANG_PATH).$sub_language_dir;
if (is_dir($dir)) {
return true;
} //even if the dir already exists, we reach the objective of having the directory there
return @mkdir($dir, api_get_permissions_for_new_directories()); // Path for the .po file you want to create
} $poFilePath = api_get_path(SYS_PATH) . self::SUBLANGUAGE_TRANS_PATH . 'messages.' . $subLanguageIsoCode . '.po';
$translationsDir = dirname($poFilePath);
/** // Check if the translations directory is writable
* Delete sub-language. if (!is_writable($translationsDir)) {
* In order to avoid deletion of main laguages, we check the existence of a parent. // Attempt to set writable permissions
* if (!@chmod($translationsDir, 0775)) { // You might adjust the permission level as needed
* @deprecated return false; // Failed to set writable permissions
*
* @param int $parent_id The parent id
* @param bool $sub_language_id
*
* @return mixed True on success, false on error
*/
public static function remove_sub_language($parent_id, $sub_language_id)
{
if (empty($parent_id) ||
(intval($parent_id) != $parent_id) ||
empty($sub_language_id) ||
(intval($sub_language_id) != $sub_language_id)
) {
return false;
}
$table = Database::get_main_table(TABLE_MAIN_LANGUAGE);
$sql = 'SELECT dokeos_folder FROM '.$table.'
WHERE parent_id = '.$parent_id.' and id = '.$sub_language_id;
$res = Database::query($sql);
if (false === $res or Database::num_rows($res) < 1) {
return false;
} }
$row = Database::fetch_assoc($res);
$res = self::remove_language_directory($row['dokeos_folder']);
if (false === $res) {
return false;
} //can't delete dir, so do not delete language record
$sql = 'DELETE FROM '.$table.'
WHERE id= '.intval($sub_language_id);
$res = Database::query($sql);
return $res;
} }
/** // If the .po file doesn't exist, create it
* Remove directory for sub-language. if (!file_exists($poFilePath)) {
* $initialContent = "# Translation file for $subLanguageIsoCode\nmsgid \"\"\nmsgstr \"\"\n";
* @param string $sub_language_dir The sub-language path directory ( e.g. 'spanish_corporate'' ) if (false === file_put_contents($poFilePath, $initialContent)) {
* return false; // Failed to write the file
* @return bool True on success, false on failure
*/
public static function remove_language_directory($sub_language_dir)
{
if (empty($sub_language_dir)) {
return false;
} }
$dir = api_get_path(SYS_LANG_PATH).$sub_language_dir;
if (!is_dir($dir)) {
return true;
} //even if the dir does not exist, we reach the objective of not having the directory there
$content = self::get_lang_folder_files_list($dir);
if (count($content) > 0) {
foreach ($content as $value_content) {
$path_file = $dir.'/'.$value_content;
unlink($path_file);
} }
return @rmdir($dir); return true;
} else {
return @rmdir($dir);
}
} }
/** /**
@ -552,4 +479,386 @@ class SubLanguageManager
return false; return false;
} }
/**
* Convert a string to a valid PHP camelCase variable name.
*
* @param string $string
* @return string
*/
public static function stringToCamelCaseVariableName($string)
{
$varName = preg_replace('/[^a-z0-9_]/i', '_', $string); // Replace invalid characters with '_'
$varName = trim($varName, '_'); // Trim any '_' from the beginning and end
$varName = ucwords(str_replace('_', ' ', $varName)); // Convert to camel case
$varName = lcfirst(str_replace(' ', '', $varName)); // Remove spaces and convert the first character to lowercase
return substr($varName, 0, 25); // Limit to 15 characters
}
/**
* Retrieve the iso_code for a given language ID and its parent.
*
* @param int $languageId
* @return array [childIsoCode, parentIsoCode]
*/
public static function getIsoCodes($languageId)
{
$em = Database::getManager();
$language = $em->getRepository('Chamilo\CoreBundle\Entity\Language')->find($languageId);
if (!$language) {
return [null, null];
}
$childIsoCode = $language->getIsoCode();
$parentIsoCode = null;
if ($language->getParent()) {
$parentLanguage = $em->getRepository('Chamilo\CoreBundle\Entity\Language')->find($language->getParent());
if ($parentLanguage) {
$parentIsoCode = $parentLanguage->getIsoCode();
}
}
return [$childIsoCode, $parentIsoCode];
}
/**
* Search for translations based on a term and language ID.
*
* @param string $term The term to search for.
* @param int $languageId The ID of the language to search in.
*
* @return array An array of matched translations.
*/
public static function searchTranslations($term, $languageId): array
{
// Retrieve the ISO codes for the provided language ID.
list($childIsoCode, $parentIsoCode) = self::getIsoCodes($languageId);
// Define the files to search in based on the ISO codes.
$files = ['en' => 'messages.en.po', $parentIsoCode => "messages.$parentIsoCode.po", $childIsoCode => "messages.$childIsoCode.po"];
$results = [];
// Step 1: Search for all matches in messages.en.po.
$matchedMsgids = self::searchMsgidInFile($term, $files['en']);
// Step 2: For each matched msgid, search for its translation in the other files.
foreach ($matchedMsgids as $msgid) {
$entry = [
'file' => $files['en'],
'variable' => $msgid,
'phpVarName' => self::stringToCamelCaseVariableName($msgid),
'en' => self::getTranslationForVariable($msgid, $files['en'])
];
$entry[$parentIsoCode] = self::getTranslationForVariable($msgid, $files[$parentIsoCode]);
$entry[$childIsoCode] = self::getTranslationForVariable($msgid, $files[$childIsoCode], true);
$results[] = $entry;
}
return $results;
}
/**
* Search for a specific term inside a given .po file and return the msgids that match.
*
* @param string $term The term to search for.
* @param string $filename The name of the .po file to search in.
*
* @return array An array of msgids that match the given term.
*/
private static function searchMsgidInFile($term, $filename)
{
$poFilePath = api_get_path(SYS_PATH) . self::LANGUAGE_TRANS_PATH . $filename;
$matchedMsgids = [];
if (file_exists($poFilePath)) {
$lines = file($poFilePath, FILE_IGNORE_NEW_LINES);
$currentVariable = null;
foreach ($lines as $line) {
if (strpos($line, 'msgid "') === 0) {
$currentVariable = str_replace('msgid "', '', $line);
$currentVariable = rtrim($currentVariable, '"');
if (stripos($currentVariable, $term) !== false) {
$matchedMsgids[] = $currentVariable;
}
}
}
}
return $matchedMsgids;
}
/**
* Retrieve the translation (msgstr) for a given variable (msgid) from a specified .po file.
*
* @param string $variable The variable (msgid) to search for.
* @param string $filename The name of the .po file to retrieve the translation from.
*
* @return string The translation (msgstr) for the provided variable, or an empty string if not found.
*/
private static function getTranslationForVariable(string $variable, string $filename, $checkSubLanguagePath = false): string
{
$poFilePath = api_get_path(SYS_PATH) . self::LANGUAGE_TRANS_PATH . $filename;
if ($checkSubLanguagePath) {
$poFilePath = api_get_path(SYS_PATH) . self::SUBLANGUAGE_TRANS_PATH . $filename;
}
if (file_exists($poFilePath)) {
$content = file_get_contents($poFilePath);
$pattern = '/msgid "' . preg_quote($variable, '/') . '"\nmsgstr "(.*?)"/';
if (preg_match($pattern, $content, $match)) {
return $match[1];
}
}
return '';
}
/**
* Updates or adds a msgid in the specified .po file.
*
* @param string $filename Name of the .po file
* @param string $msgid Message identifier to search or add
* @param string $content Associated message content
*
* @return array Returns true if the operation was successful, otherwise returns false
*/
public static function updateOrAddMsgid($filename, $msgid, $content): array
{
$filePath = api_get_path(SYS_PATH) . self::SUBLANGUAGE_TRANS_PATH . $filename;
if (!file_exists($filePath)) {
return ['success' => false, 'error' => 'File does not exist'];
}
if (!is_writable($filePath)) {
try {
if (!chmod($filePath, 0664)) {
return ['success' => false, 'error' => 'Unable to set the file to writable'];
}
} catch (Exception $e) {
return ['success' => false, 'error' => 'Failed to change file permissions: ' . $e->getMessage()];
}
}
$fileContents = file_get_contents($filePath);
if ($fileContents === false) {
return ['success' => false, 'error' => 'Failed to read file contents'];
}
$pattern = '/msgid "' . preg_quote($msgid, '/') . '"' . PHP_EOL . 'msgstr "(.*?)"/';
if (preg_match($pattern, $fileContents)) {
$replacement = 'msgid "' . $msgid . '"' . PHP_EOL . 'msgstr "' . $content . '"';
$fileContents = preg_replace($pattern, $replacement, $fileContents);
} else {
$appendString = PHP_EOL . PHP_EOL . 'msgid "' . $msgid . '"' . PHP_EOL . 'msgstr "' . $content . '"';
$fileContents .= $appendString;
}
if (file_put_contents($filePath, $fileContents) === false) {
return ['success' => false, 'error' => 'Failed to write to file'];
}
return ['success' => true];
}
/**
* Delete sub-language.
* In order to avoid deletion of main languages, we check the existence of a parent.
*/
public static function removeSubLanguage(int $parentId, int $subLanguageId): bool
{
$entityManager = Database::getManager();
$subLanguage = $entityManager->getRepository(Language::class)->find($subLanguageId);
$parentLanguage = $subLanguage ? $subLanguage->getParent() : null;
if (!$subLanguage || !$parentLanguage || $parentLanguage->getId() != $parentId) {
return false;
}
// Locate and delete the .po file of the sub-language
$subLanguageIsoCode = $subLanguage->getIsocode();
$poFilePath = api_get_path(SYS_PATH) . self::SUBLANGUAGE_TRANS_PATH . "messages.$subLanguageIsoCode.po";
if (file_exists($poFilePath)) {
unlink($poFilePath);
}
$entityManager->remove($subLanguage);
$entityManager->flush();
return true;
}
/**
* Add a sub-language.
*/
public static function addSubLanguage(string $originalName, string $englishName, bool $isAvailable, int $parentId): bool|int
{
$entityManager = Database::getManager();
$parentLanguage = $entityManager->getRepository(Language::class)->find($parentId);
if (!$parentLanguage) {
return false;
}
$subLanguage = new Language();
$subLanguage->setOriginalName($originalName)
->setEnglishName($englishName)
->setIsocode($englishName)
->setAvailable($isAvailable)
->setParent($parentLanguage);
try {
$entityManager->persist($subLanguage);
$entityManager->flush();
} catch (\Exception $e) {
// Handle exception if needed
return false;
}
return $subLanguage->getId();
}
/**
* Remove a .po file for a sub-language.
*
* @param string $isoCode The ISO code of the sub-language (e.g., 'es_CO')
*
* @return bool True on success, false on failure
*/
public static function removePoFileForSubLanguage(string $isoCode): bool
{
if (empty($isoCode)) {
return false;
}
// Path for the .po file you want to remove
$poFilePath = api_get_path(SYS_PATH) . self::SUBLANGUAGE_TRANS_PATH . "messages.$isoCode.po";
if (file_exists($poFilePath)) {
return unlink($poFilePath);
}
// File does not exist, consider it a successful removal
return true;
}
/**
* Check if a language exists by its ID.
*/
public static function languageExistsById(int $languageId): bool
{
$entityManager = Database::getManager();
$language = $entityManager->getRepository(Language::class)->find($languageId);
return $language !== null;
}
/**
* Check if the given language is a parent of any sub-language.
*/
public static function isParentOfSubLanguage(int $parentId): bool
{
$entityManager = Database::getManager();
$languageRepository = $entityManager->getRepository(Language::class);
$childrenCount = $languageRepository->count(['parent' => $parentId]);
return $childrenCount > 0;
}
/**
* Get all information of a sub-language.
*/
public static function getAllInformationOfSubLanguage(int $parentId, int $subLanguageId): array
{
$entityManager = Database::getManager();
$languageRepository = $entityManager->getRepository(Language::class);
$subLanguage = $languageRepository->findOneBy([
'parent' => $parentId,
'id' => $subLanguageId
]);
return $subLanguage ? self::convertLanguageToArray($subLanguage) : [];
}
/**
* Convert a Language entity to an array.
*/
private static function convertLanguageToArray(Language $language): array
{
return [
'id' => $language->getId(),
'original_name' => $language->getOriginalName(),
'english_name' => $language->getEnglishName(),
'isocode' => $language->getIsocode(),
'available' => $language->getAvailable(),
// Add other fields as needed
];
}
/**
* Check if a language exists.
*/
public static function checkIfLanguageExists(string $originalName, string $englishName, string $isoCode): array
{
$entityManager = Database::getManager();
$languageRepository = $entityManager->getRepository(Language::class);
$messageInformation = [
'original_name' => false,
'english_name' => false,
'isocode' => false,
'execute_add' => true
];
if ($languageRepository->count(['originalName' => $originalName]) > 0) {
$messageInformation['original_name'] = true;
$messageInformation['execute_add'] = false;
}
if ($languageRepository->count(['englishName' => $englishName]) > 0) {
$messageInformation['english_name'] = true;
$messageInformation['execute_add'] = false;
}
$isoList = api_get_platform_isocodes(); // Assuming this is an existing function
if (!in_array($isoCode, array_values($isoList))) {
$messageInformation['isocode'] = true;
$messageInformation['execute_add'] = false;
}
return $messageInformation;
}
/**
* Gets the ISO code of the parent language for a given language.
*/
public static function getParentLocale(string $childIsoCode): ?string
{
$em = Database::getManager();
$languageRepository = $em->getRepository('Chamilo\CoreBundle\Entity\Language');
// Find the language by its ISO code
$language = $languageRepository->findOneBy(['isocode' => $childIsoCode]);
if (!$language) {
return null; // Language not found
}
// Get the parent language if it exists
$parentLanguage = $language->getParent();
if ($parentLanguage) {
return $parentLanguage->getIsocode();
}
return null; // No parent language
}
} }

@ -6,6 +6,7 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Command; namespace Chamilo\CoreBundle\Command;
use Chamilo\CoreBundle\Entity\Language;
use Chamilo\CoreBundle\Repository\LanguageRepository; use Chamilo\CoreBundle\Repository\LanguageRepository;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -69,7 +70,8 @@ class UpdateVueTranslations extends Command
$newLanguage = []; $newLanguage = [];
foreach ($translations as $variable => $translation) { foreach ($translations as $variable => $translation) {
$translated = $this->translator->trans($variable, [], null, $iso); //$translated = $this->translator->trans($variable, [], null, $iso);
$translated = $this->getTranslationWithFallback($variable, $language);
$newLanguage[$variable] = $this->replaceMarkers($translated); $newLanguage[$variable] = $this->replaceMarkers($translated);
} }
$newLanguageToString = json_encode($newLanguage, JSON_PRETTY_PRINT); $newLanguageToString = json_encode($newLanguage, JSON_PRETTY_PRINT);
@ -83,6 +85,37 @@ class UpdateVueTranslations extends Command
return Command::SUCCESS; return Command::SUCCESS;
} }
/**
* Gets the translation for a given variable with fallbacks to parent language and base language.
*
* @param string $variable The variable to be translated.
* @param Language $language The Language entity for the current language.
*
* @return string The translated string.
*/
private function getTranslationWithFallback(string $variable, Language $language): string {
// Get the ISO code of the current language
$iso = $language->getIsocode();
// Try to translate the variable in the current language
$translated = $this->translator->trans($variable, [], 'messages', $iso);
// Check if the translation is not found and if there is a parent language
if ($translated === $variable && $language->getParent()) {
// Get the parent language entity and its ISO code
$parentLanguage = $language->getParent();
$parentIso = $parentLanguage->getIsocode();
// Try to translate the variable in the parent language
$translated = $this->translator->trans($variable, [], 'messages', $parentIso);
// Check if translation is still not found and use the base language (English)
if ($translated === $variable) {
$translated = $this->translator->trans($variable, [], 'messages', 'en');
}
}
return $translated;
}
/** /**
* Replace specifiers in a string to allow rendering them by i18n. * Replace specifiers in a string to allow rendering them by i18n.
* *

Loading…
Cancel
Save