Merge pull request #5109 from christianbeeznest/GH-3761

Migration: Migration of sublanguages and Vue translation updates - refs #3761
pull/5110/head
christianbeeznest 2 years ago committed by GitHub
commit 86e01b1d7b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      public/main/admin/sub_language_add.php
  2. 18
      public/main/inc/lib/sub_language.class.php
  3. 190
      src/CoreBundle/Migrations/Schema/V200/Version20240122221400.php

@ -110,16 +110,16 @@ if (isset($_POST['SubmitAddNewLanguage'])) {
$english_name = api_strtolower($english_name);
$firstIso = substr($language_details['isocode'], 0, 2);
$english_name = str_starts_with($english_name, $firstIso.'_') ? $english_name : $firstIso.'_'.$english_name;
//$english_name = str_starts_with($english_name, $firstIso.'_') ? $english_name : $firstIso.'_'.$english_name;
$isocode = str_replace(' ', '_', $isocode);
$isocode = SubLanguageManager::generateSublanguageCode($firstIso, $_POST['english_name']);
$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::addPoFileForSubLanguage($english_name);
$mkdir_result = SubLanguageManager::addPoFileForSubLanguage($isocode);
if ($mkdir_result) {
$sl_id = SubLanguageManager::addSubLanguage($original_name, $english_name, $sublanguage_available, $parent_id);
$sl_id = SubLanguageManager::addSubLanguage($original_name, $english_name, $sublanguage_available, $parent_id, $isocode);
if (false === $sl_id) {
SubLanguageManager::removePoFileForSubLanguage($english_name);
SubLanguageManager::removePoFileForSubLanguage($isocode);
$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 {
Display::addFlash(

@ -716,7 +716,7 @@ class SubLanguageManager
/**
* Add a sub-language.
*/
public static function addSubLanguage(string $originalName, string $englishName, bool $isAvailable, int $parentId): bool|int
public static function addSubLanguage(string $originalName, string $englishName, bool $isAvailable, int $parentId, string $isoCode): bool|int
{
$entityManager = Database::getManager();
$parentLanguage = $entityManager->getRepository(Language::class)->find($parentId);
@ -727,7 +727,7 @@ class SubLanguageManager
$subLanguage = new Language();
$subLanguage->setOriginalName($originalName)
->setEnglishName($englishName)
->setIsocode($englishName)
->setIsocode($isoCode)
->setAvailable($isAvailable)
->setParent($parentLanguage);
@ -878,4 +878,18 @@ class SubLanguageManager
return null; // No parent language
}
public static function generateSublanguageCode(string $parentCode, string $variant, int $maxLength = 10): string
{
$parentCode = strtolower(trim($parentCode));
$variant = strtolower(trim($variant));
// Generate a variant code by truncating the variant name
$variantCode = substr($variant, 0, $maxLength - strlen($parentCode) - 1);
// Build the complete code
$fullCode = substr($parentCode . '_' . $variantCode, 0, $maxLength);
return $fullCode;
}
}

@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Schema\Schema;
use SubLanguageManager;
use Symfony\Component\Process\Process;
final class Version20240122221400 extends AbstractMigrationChamilo
{
public function getDescription(): string
{
return 'Migration of sublanguages and Vue translation updates.';
}
public function up(Schema $schema): void
{
$container = $this->getContainer();
$doctrine = $container->get('doctrine');
$em = $doctrine->getManager();
/** @var Connection $connection */
$connection = $em->getConnection();
// Default sublanguages to be excluded from the update.
$defaultSubLanguages = ['ast', 'ast_ES', 'ca', 'ca_ES', 'eo', 'gl', 'qu', 'quz_PE', 'zh-TW', 'zh_TW', 'pt-BR', 'pt_PT', 'fur', 'fur_IT', 'oc', 'oc_FR'];
// Fetching sublanguages from the database.
$sql = "SELECT * FROM language WHERE parent_id IS NOT NULL AND isocode NOT IN('" . implode("', '", $defaultSubLanguages) . "')";
$sublanguages = $connection->executeQuery($sql)->fetchAllAssociative();
foreach ($sublanguages as $sublanguage) {
$newIsoCode = $this->updateAndGenerateSubLanguage($sublanguage, $connection);
$this->generatePoFileFromTrad4All($sublanguage['english_name'], $newIsoCode);
}
// Update Vue translations after processing all sublanguages.
$this->executeVueTranslationsUpdate();
}
private function updateAndGenerateSubLanguage(array $sublanguage, Connection $connection): string
{
// Get the parent language ID
$parentId = $sublanguage['parent_id'];
// Query to obtain the isocode of the parent language
$parentIsoQuery = "SELECT isocode FROM language WHERE id = ?";
$parentIsoCode = $connection->executeQuery($parentIsoQuery, [$parentId])->fetchOne();
// Get the prefix of the parent language's isocode
$firstIso = substr($parentIsoCode, 0, 2);
$newIsoCode = $this->generateSublanguageCode($firstIso, $sublanguage['english_name']);
// Update the isocode in the language table
$updateLanguageQuery = "UPDATE language SET isocode = ? WHERE id = ?";
$connection->executeStatement($updateLanguageQuery, [$newIsoCode, $sublanguage['id']]);
error_log("Updated language table for id " . $sublanguage['id']);
// Check and update in settings_current
$updateSettingsQuery = "UPDATE settings_current SET selected_value = ? WHERE variable = 'platform_language' AND selected_value = ?";
$connection->executeStatement($updateSettingsQuery, [$newIsoCode, $sublanguage['english_name']]);
error_log("Updated settings_current for language " . $sublanguage['english_name']);
// Check and update in user table
$updateUserQuery = "UPDATE user SET locale = ? WHERE locale = ?";
$connection->executeStatement($updateUserQuery, [$newIsoCode, $sublanguage['english_name']]);
error_log("Updated user table for language " . $sublanguage['english_name']);
// Check and update in course table
$updateCourseQuery = "UPDATE course SET course_language = ? WHERE course_language = ?";
$connection->executeStatement($updateCourseQuery, [$newIsoCode, $sublanguage['english_name']]);
error_log("Updated course table for language " . $sublanguage['english_name']);
// Return the new ISO code.
return $newIsoCode;
}
private function generatePoFileFromTrad4All(string $englishName, string $isocode): void
{
$container = $this->getContainer();
$kernel = $container->get('kernel');
$rootPath = $kernel->getProjectDir();
$langPath = $rootPath . '/public/main/lang/' . $englishName . '/trad4all.inc.php';
$destinationFilePath = $rootPath . '/var/translations/messages.' . $isocode . '.po';
$originalFile = $rootPath.'/public/main/lang/english/trad4all.inc.php';
if (!file_exists($langPath)) {
error_log("Original file not found: $langPath");
return;
}
$terms = SubLanguageManager::get_all_language_variable_in_file(
$originalFile,
true
);
foreach ($terms as $index => $translation) {
$terms[$index] = trim(rtrim($translation, ';'), '"');
}
$header = 'msgid ""'."\n".'msgstr ""'."\n".
'"Project-Id-Version: chamilo\n"'."\n".
'"Language: '.$isocode.'\n"'."\n".
'"Content-Type: text/plain; charset=UTF-8\n"'."\n".
'"Content-Transfer-Encoding: 8bit\n"'."\n\n";
file_put_contents($destinationFilePath, $header);
$originalTermsInLanguage = SubLanguageManager::get_all_language_variable_in_file(
$langPath,
true
);
foreach ($originalTermsInLanguage as $id => $content) {
if (!isset($termsInLanguage[$id])) {
$termsInLanguage[$id] = trim(rtrim($content, ';'), '"');
}
}
$bigString = '';
$doneTranslations = [];
foreach ($terms as $term => $englishTranslation) {
if (isset($doneTranslations[$englishTranslation])) {
continue;
}
$doneTranslations[$englishTranslation] = true;
$translatedTerm = '';
if (!empty($termsInLanguage[$term])) {
$translatedTerm = $termsInLanguage[$term];
}
// Here we apply a little correction to avoid unterminated strings
// when a string ends with a \"
if (preg_match('/\\\$/', $englishTranslation)) {
$englishTranslation .= '"';
}
$search = ['\\{', '\\}', '\\(', '\\)', '\\;'];
$replace = ['\\\\{', '\\\\}', '\\\\(', '\\\\)', '\\\\;'];
$englishTranslation = str_replace($search, $replace, $englishTranslation);
if (preg_match('/\\\$/', $translatedTerm)) {
$translatedTerm .= '"';
}
$translatedTerm = str_replace($search, $replace, $translatedTerm);
if (empty($translatedTerm)) {
continue;
}
// Now build the line
$bigString .= 'msgid "'.$englishTranslation.'"'."\n".'msgstr "'.$translatedTerm.'"'."\n\n";
}
file_put_contents($destinationFilePath, $bigString, FILE_APPEND);
error_log("Done generating gettext file in $destinationFilePath !\n");
}
private function executeVueTranslationsUpdate(): void
{
$process = new Process(['php', 'bin/console', 'chamilo:update_vue_translations']);
$process->run();
if (!$process->isSuccessful()) {
throw new \RuntimeException($process->getErrorOutput());
}
echo $process->getOutput();
}
private function generateSublanguageCode(string $parentCode, string $variant, int $maxLength = 10): string
{
$parentCode = strtolower(trim($parentCode));
$variant = strtolower(trim($variant));
// Generate a variant code by truncating the variant name
$variantCode = substr($variant, 0, $maxLength - strlen($parentCode) - 1);
// Build the complete code
$fullCode = substr($parentCode . '_' . $variantCode, 0, $maxLength);
return $fullCode;
}
public function down(Schema $schema): void
{
}
}
Loading…
Cancel
Save