/** * Handles enabling translations for controllers that are not pages */ public function onBeforeInit() { //Bail for the root url controller and model as controller classes as they handle this internally, also disable for development admin and cms if ($this->owner instanceof MultilingualRootURLController || $this->owner instanceof MultilingualModelAsController || $this->owner instanceof LeftAndMain || $this->owner instanceof DevelopmentAdmin || $this->owner instanceof TestRunner) { return; } //Bail for pages since this would have been handled by MultilingualModelAsController, we're assuming that data has not been set to a page by other code if (method_exists($this->owner, 'data') && $this->owner->data() instanceof SiteTree) { return; } //Check if the locale is in the url $request = $this->owner->getRequest(); if ($request && $request->param('Language')) { $language = $request->param('Language'); if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { $locale = $language; } else { if (strpos($request->param('Language'), '_') !== false) { //Invalid format so redirect to the default $url = $request->getURL(true); $default = Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL') ? Translatable::default_locale() : Translatable::default_lang(); $this->owner->redirect(preg_replace('/^' . preg_quote($language, '/') . '\\//', $default . '/', $url), 301); return; } else { $locale = i18n::get_locale_from_lang($language); } } if (in_array($locale, Translatable::get_allowed_locales())) { //Set the language cookie Cookie::set('language', $language); //Set the various locales Translatable::set_current_locale($locale); i18n::set_locale($locale); } else { //Unknown language so redirect to the default $url = $request->getURL(true); $default = Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL') ? Translatable::default_locale() : Translatable::default_lang(); $this->owner->redirect(preg_replace('/^' . preg_quote($language, '/') . '\\//', $default . '/', $url), 301); } return; } //Detect the locale if ($locale = MultilingualRootURLController::detect_browser_locale()) { if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { $language = $locale; } else { $language = i18n::get_lang_from_locale($locale); } //Set the language cookie Cookie::set('language', $language); //Set the various locales Translatable::set_current_locale($locale); i18n::set_locale($locale); } }
/** * Try very hard to get a locale for this user. Helps for i18n etc. * @return string */ public static function get_smart_locale($language = null) { require_once FRAMEWORK_PATH . '/thirdparty/Zend/Locale.php'; $locale = Zend_Locale::getBrowser(); if (!$locale) { if ($language) { return i18n::get_locale_from_lang($language); } else { return i18n::get_locale(); } } $locale = array_keys($locale); $firstPref = array_shift($locale); if (strpos($firstPref, '_') === false) { return i18n::get_locale_from_lang($language); } return $firstPref; }
/** * For field types that can contain a variety of data, e.g. Varchar, this method * informs the Faker\Generator object what kind of data to generate based on the name of the field. * For instance, a field named "FirstName" should generate a person's name. A field named "Country" should * generate a country name. * * Field names can be matched at the beginning or end of the string, for instance: * "DoctorFirstName" and "Address2" will generate a first name and an address, respectively. * * This logic can be refined in the lang file so that database fields can be named in the local language, * e.g. "Prenom" or "Pays" and still be mapped to the correct data type. * * @param string $name The name of the data type to examine * @return boolean */ public function hook($name) { $list = false; $current_locale = i18n::get_locale(); $default_lang = Config::inst()->forClass("MockDBField")->default_lang; $default_locale = i18n::get_locale_from_lang($default_lang); i18n::set_locale($default_locale); $core_list = _t('MockDataObject.' . $name); i18n::set_locale($current_locale); $user_list = _t('MockDataObject.' . $name); $list = $user_list ?: $core_list; if ($list) { $candidates = explode(",", $list); $fieldName = $this->owner->getName(); foreach ($candidates as $c) { $c = trim($c); if (preg_match('/^' . $c . '[A-Z0-9]*/', $fieldName) || preg_match('/' . $c . '$/', $fieldName)) { return true; } } } return false; }
function run($request) { $ids = array(); echo "#################################\n"; echo "# Adding translation groups to existing records" . "\n"; echo "#################################\n"; $allSiteTreeIDs = DB::query('SELECT `ID` FROM `SiteTree`')->column(); if ($allSiteTreeIDs) { foreach ($allSiteTreeIDs as $id) { $original = DataObject::get_by_id('SiteTree', $id); $existingGroupID = $original->getTranslationGroup(); if (!$existingGroupID) { $original->addTranslationGroup($original->ID); } $original->destroy(); unset($original); } } DataObject::flush_and_destroy_cache(); echo sprintf("Created translation groups for %d records\n", count($allSiteTreeIDs)); foreach (array('Stage', 'Live') as $stage) { echo "\n\n#################################\n"; echo "# Migrating stage {$stage}" . "\n"; echo "#################################\n"; $suffix = $stage == 'Live' ? '_Live' : ''; // First get all entries in SiteTree_lang // This should be all translated pages $trans = DB::query(sprintf('SELECT * FROM `_obsolete_SiteTree_lang%s`', $suffix)); // Iterate over each translated pages foreach ($trans as $oldtrans) { $newLocale = i18n::get_locale_from_lang($oldtrans['Lang']); echo sprintf("Migrating from %s to %s translation of '%s' (#%d)\n", $oldtrans['Lang'], $newLocale, Convert::raw2xml($oldtrans['Title']), $oldtrans['OriginalLangID']); // Get the untranslated page $original = Versioned::get_one_by_stage($oldtrans['ClassName'], $stage, '`SiteTree`.`ID` = ' . $oldtrans['OriginalLangID']); if (!$original) { echo sprintf("Couldn't find original for #%d", $oldtrans['OriginalLangID']); continue; } // write locale to $original $original->Locale = i18n::get_locale_from_lang(Translatable::default_lang()); $original->writeToStage($stage); // Clone the original, and set it up as a translation $existingTrans = $original->getTranslation($newLocale, $stage); if ($existingTrans) { echo sprintf("Found existing new-style translation for #%d. Already merged? Skipping.\n", $oldtrans['OriginalLangID']); continue; } // Doesn't work with stage/live split //$newtrans = $original->createTranslation($newLocale); $newtrans = $original->duplicate(false); $newtrans->OriginalID = $original->ID; // we have to "guess" a locale based on the language $newtrans->Locale = $newLocale; if ($stage == 'Live' && array_key_exists($original->ID, $ids)) { $newtrans->ID = $ids[$original->ID]; } // Look at each class in the ancestry, and see if there is a _lang table for it foreach (ClassInfo::ancestry($oldtrans['ClassName']) as $classname) { $oldtransitem = false; // If the class is SiteTree, we already have the DB record, else check for the table and get the record if ($classname == 'SiteTree') { $oldtransitem = $oldtrans; } elseif (in_array(strtolower($classname) . '_lang', DB::tableList())) { $oldtransitem = DB::query(sprintf('SELECT * FROM `_obsolete_%s_lang%s` WHERE `OriginalLangID` = %d AND `Lang` = \'%s\'', $classname, $suffix, $original->ID, $oldtrans['Lang']))->first(); } // Copy each translated field into the new translation if ($oldtransitem) { foreach ($oldtransitem as $key => $value) { if (!in_array($key, array('ID', 'OriginalLangID'))) { $newtrans->{$key} = $value; } } } } // Write the new translation to the database $sitelang = Translatable::get_current_locale(); Translatable::set_current_locale($newtrans->Locale); $newtrans->writeToStage($stage); Translatable::set_current_locale($sitelang); $newtrans->addTranslationGroup($original->getTranslationGroup(), true); if ($stage == 'Stage') { $ids[$original->ID] = $newtrans->ID; } } } echo "\n\n#################################\n"; echo "Done!\n"; }
public function testGetLocaleFromLang() { $this->assertEquals('en_US', i18n::get_locale_from_lang('en')); $this->assertEquals('de_DE', i18n::get_locale_from_lang('de_DE')); $this->assertEquals('xy_XY', i18n::get_locale_from_lang('xy')); }
/** * @deprecated 2.4 Use get_one_by_locale() */ static function get_one_by_lang($class, $lang, $filter = '', $cache = false, $orderby = "") { return self::get_one_by_locale($class, i18n::get_locale_from_lang($lang), $filter, $cache, $orderby); }
/** * Determines the locale best matching the given list of browser locales * @return {string} The matching locale, or null if none could be determined */ public static function detect_browser_locale() { if ($language = Cookie::get('language')) { if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { $locale = $language; } else { $locale = i18n::get_locale_from_lang($language); } if (in_array($locale, Translatable::get_allowed_locales())) { return $locale; } else { Cookie::force_expiry('language'); } } // Given multiple canditates, narrow down the final result using the client's preferred languages $inputLocales = array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : null; if (empty($inputLocales)) { return null; } // Generate mapping of priority => list of languages at this priority // break up string into pieces (languages and q factors) preg_match_all('/(?<code>[a-z]{1,8}(-[a-z]{1,8})?)\\s*(;\\s*q\\s*=\\s*(?<priority>1|0\\.[0-9]+))?/i', $inputLocales, $parsedLocales); $prioritisedLocales = array(); if (count($parsedLocales['code'])) { // create a list like "en" => 0.8 $parsedLocales = array_combine($parsedLocales['code'], $parsedLocales['priority']); // Generate nested list of priorities => [languages] foreach ($parsedLocales as $language => $priority) { $priority = empty($priority) ? 1.0 : floatval($priority); if (empty($prioritisedLocales[$priority])) { $prioritisedLocales[$priority] = array(); } $prioritisedLocales[$priority][] = $language; } // sort list based on value krsort($prioritisedLocales, SORT_NUMERIC); } // Check each requested language against loaded languages foreach ($prioritisedLocales as $priority => $parsedLocales) { foreach ($parsedLocales as $browserLocale) { foreach (Translatable::get_allowed_locales() as $language) { if (stripos(preg_replace('/_/', '-', $language), $browserLocale) === 0) { return $language; } } } } return null; }
$country->ISO3 = "ZWE"; $country->FIPS = "ZI"; $country->ISON = "716"; $country->Title = _t("SilvercartCountry.TITLE_ZW"); $country->Continent = "AF"; $country->Currency = "ZWL"; $country->Locale = Translatable::get_current_locale(); $country->write(); } $translatorsByPrio = i18n::get_translators(); foreach ($translatorsByPrio as $priority => $translators) { foreach ($translators as $name => $translator) { $adapter = $translator->getAdapter(); $languages = $adapter->getList(); foreach ($languages as $language) { $locale = i18n::get_locale_from_lang($language); if ($country->hasLanguage($locale)) { continue; } $data = $adapter->getMessages($language); foreach (SilvercartCountry::get() as $country) { $key = 'TITLE_' . strtoupper($country->ISO2); if (array_key_exists('SilvercartCountry.' . $key, $data)) { $translation = new SilvercartCountryLanguage(); $translation->Locale = $locale; $translation->Title = $data['SilvercartCountry.' . $key]; $translation->write(); $country->SilvercartCountryLanguages()->add($translation); } } }
public function run($request) { echo 'Run with ?clear=1 to clear empty database before running the task<br/>'; echo 'Run with ?overwrite=soft|hard to overwrite templates that exists in the cms. Soft will replace template if not modified by the user, hard will replace template even if modified by user.<br/>'; echo 'Run with ?templates=xxx,yyy to specify which template should be imported<br/>'; echo 'Run with ?subsite=all|subsiteID to create email templates in all subsites (including main site) or only in the chosen subsite (if a subsite is active, it will be used by default).<br/>'; echo 'Run with ?locales=fr,en to choose which locale to import.<br/>'; echo '<strong>Remember to flush the templates/translations if needed</strong><br/>'; echo '<hr/>'; $overwrite = $request->getVar('overwrite'); $clear = $request->getVar('clear'); $templatesToImport = $request->getVar('templates'); $importToSubsite = $request->getVar('subsite'); $chosenLocales = $request->getVar('locales'); // Normalize argument if ($overwrite && $overwrite != 'soft' && $overwrite != 'hard') { $overwrite = 'soft'; } $subsites = array(); if ($importToSubsite == 'all') { $subsites = Subsite::get()->map(); } else { if (is_numeric($importToSubsite)) { $subsites = array($importToSubsite => Subsite::get()->byID($importToSubsite)->Title); } } if (class_exists('Subsite') && Subsite::currentSubsiteID()) { DB::alteration_message("Importing to current subsite. Run from main site to import other subsites at once.", "created"); $subsites = array(); } if (!empty($subsites)) { DB::alteration_message("Importing to subsites : " . implode(',', array_values($subsites)), "created"); } if ($templatesToImport) { $templatesToImport = explode(',', $templatesToImport); } if ($clear == 1) { DB::alteration_message("Clear all email templates", "created"); $emailTemplates = EmailTemplate::get(); foreach ($emailTemplates as $emailTemplate) { $emailTemplate->delete(); } } $emailTemplateSingl = singleton('EmailTemplate'); $ignoredModules = self::config()->ignored_modules; if (!is_array($ignoredModules)) { $ignoredModules = array(); } $locales = null; if (class_exists('Fluent') && Fluent::locale_names()) { if ($emailTemplateSingl->hasExtension('FluentExtension')) { $locales = array_keys(Fluent::locale_names()); if ($chosenLocales) { $arr = explode(',', $chosenLocales); $locales = array(); foreach ($arr as $a) { if (strlen($a) == 2) { $a = i18n::get_locale_from_lang($a); } $locales[] = $a; } } } } $defaultLocale = i18n::get_locale(); $templates = SS_TemplateLoader::instance()->getManifest()->getTemplates(); foreach ($templates as $t) { $isOverwritten = false; // Emails in mysite/email are not properly marked as emails if (isset($t['mysite']) && isset($t['mysite']['email'])) { $t['email'] = $t['mysite']['email']; } // Should be in the /email folder if (!isset($t['email'])) { continue; } $filePath = $t['email']; $fileName = basename($filePath, '.ss'); // Should end with *Email if (!preg_match('/Email$/', $fileName)) { continue; } $relativeFilePath = str_replace(Director::baseFolder(), '', $filePath); $relativeFilePathParts = explode('/', trim($relativeFilePath, '/')); // Group by module $module = array_shift($relativeFilePathParts); // Ignore some modules if (in_array($module, $ignoredModules)) { continue; } array_shift($relativeFilePathParts); // remove /templates part $templateName = str_replace('.ss', '', implode('/', $relativeFilePathParts)); $templateTitle = basename($templateName); // Create a default code from template name $code = strtolower(preg_replace('/([a-zA-Z])(?=[A-Z])/', '$1-', $fileName)); $code = preg_replace('/-email$/', '', $code); if (!empty($templatesToImport) && !in_array($code, $templatesToImport)) { DB::alteration_message("Template with code <b>{$code}</b> was ignored.", "repaired"); continue; } $whereCode = array('Code' => $code); $emailTemplate = EmailTemplate::get()->filter($whereCode)->first(); // Check if it has been modified or not $templateModified = false; if ($emailTemplate) { $templateModified = $emailTemplate->Created != $emailTemplate->LastEdited; } if (!$overwrite && $emailTemplate) { DB::alteration_message("Template with code <b>{$code}</b> already exists. Choose overwrite if you want to import again.", "repaired"); continue; } if ($overwrite == 'soft' && $templateModified) { DB::alteration_message("Template with code <b>{$code}</b> has been modified by the user. Choose overwrite=hard to change.", "repaired"); continue; } // Create a default title from code $title = explode('-', $code); $title = array_map(function ($item) { return ucfirst($item); }, $title); $title = implode(' ', $title); // Get content of the email $content = file_get_contents($filePath); // Analyze content to find incompatibilities $errors = array(); if (strpos($content, '<% with') !== false) { $errors[] = 'Replace "with" blocks by plain calls to the variable'; } if (strpos($content, '<% if') !== false) { $errors[] = 'If/else logic is not supported. Please create one template by use case or abstract logic into the model'; } if (strpos($content, '<% loop') !== false) { $errors[] = 'Loops are not supported. Please create a helper method on the model to render the loop'; } if (strpos($content, '<% sprintf') !== false) { $errors[] = 'You should not use sprintf to escape content, please use plain _t calls'; } if (!empty($errors)) { echo "<div style='color:red'>Invalid syntax was found in '{$relativeFilePath}'. Please fix these errors before importing the template<ul>"; foreach ($errors as $error) { echo '<li>' . $error . '</li>'; } echo '</ul></div>'; continue; } // Parse language $collector = new i18nTextCollector(); $entities = $collector->collectFromTemplate($content, $fileName, $module); $translationTable = array(); foreach ($entities as $entity => $data) { if ($locales) { foreach ($locales as $locale) { i18n::set_locale($locale); if (!isset($translationTable[$entity])) { $translationTable[$entity] = array(); } $translationTable[$entity][$locale] = i18n::_t($entity); } i18n::set_locale($defaultLocale); } else { $translationTable[$entity] = array($defaultLocale => i18n::_t($entity)); } } $contentLocale = array(); foreach ($locales as $locale) { $contentLocale[$locale] = $content; } foreach ($translationTable as $entity => $translationData) { $escapedEntity = str_replace('.', '\\.', $entity); $baseTranslation = null; foreach ($translationData as $locale => $translation) { if (!$baseTranslation && $translation) { $baseTranslation = $translation; } if (!$translation) { $translation = $baseTranslation; } // This regex should match old and new style $count = 0; $contentLocale[$locale] = preg_replace("/<%(t | _t\\(')" . $escapedEntity . "( |').*?%>/ums", $translation, $contentLocale[$locale], -1, $count); if (!$count) { throw new Exception("Failed to replace {$escapedEntity} with translation {$translation}"); } } } if (!$emailTemplate) { $emailTemplate = new EmailTemplate(); } else { $isOverwritten = true; } // Scan for extra models based on convention preg_match_all('/\\$([a-zA-Z]+)\\./ms', $contentLocale[$defaultLocale], $matches); $extraModels = array(); if (!empty($matches) && !empty($matches[1])) { $arr = array_unique($matches[1]); foreach ($arr as $n) { if (strtolower($n) === 'siteconfig') { continue; } if (class_exists($n)) { $extraModels[$n] = $n; } } } // Apply content to email $this->assignContent($emailTemplate, $contentLocale[$defaultLocale]); if (!empty($locales)) { foreach ($locales as $locale) { $this->assignContent($emailTemplate, $contentLocale[$locale], $locale); } } // Title $emailTemplate->Title = $title; if (!empty($locales)) { // By convention, we store the translation under NameOfTheTemplateEmail.SUBJECT foreach ($locales as $locale) { i18n::set_locale($locale); $localeField = 'Title_' . $locale; $entity = $templateTitle . '.SUBJECT'; $translation = i18n::_t($entity); if (!$translation) { $translation = $title; DB::alteration_message("No title found in {$locale} for {$title}. You should define {$templateTitle}.SUBJECT", "error"); } $emailTemplate->{$localeField} = $translation; if (strpos($translation, '%s') !== false) { echo '<div style="color:red">There is a %s in the title that should be replaced in locale ' . $locale . '!</div>'; } if ($locale == $defaultLocale) { $emailTemplate->Title = $translation; } } i18n::set_locale($defaultLocale); } // Other properties $emailTemplate->Code = $code; $emailTemplate->Category = $module; if (class_exists('Subsite') && Subsite::currentSubsiteID()) { $emailTemplate->SubsiteID = Subsite::currentSubsiteID(); } $emailTemplate->setExtraModelsAsArray($extraModels); // Write to main site or current subsite $emailTemplate->write(); $this->resetLastEditedDate($emailTemplate->ID); // Loop through subsites if (!empty($importToSubsite)) { Subsite::$disable_subsite_filter = true; foreach ($subsites as $subsiteID => $subsiteTitle) { $whereCode['SubsiteID'] = $subsiteID; $subsiteEmailTemplate = EmailTemplate::get()->filter($whereCode)->first(); $emailTemplateCopy = $emailTemplate; $emailTemplateCopy->SubsiteID = $subsiteID; if ($subsiteEmailTemplate) { $emailTemplateCopy->ID = $subsiteEmailTemplate->ID; } else { $emailTemplateCopy->ID = 0; // New } $emailTemplateCopy->write(); $this->resetLastEditedDate($emailTemplateCopy->ID); } } if ($isOverwritten) { DB::alteration_message("Overwrote <b>{$emailTemplate->Code}</b>", "created"); } else { DB::alteration_message("Imported <b>{$emailTemplate->Code}</b>", "created"); } } }
/** * Switch to another subsite through storing the subsite identifier in the current PHP session. * Only takes effect when {@link Subsite::$use_session_subsiteid} is set to TRUE. * * @param int|Subsite $subsite Either the ID of the subsite, or the subsite object itself */ public static function changeSubsite($subsite) { // Session subsite change only meaningful if the session is active. // Otherwise we risk setting it to wrong value, e.g. if we rely on currentSubsiteID. if (!Subsite::$use_session_subsiteid) { return; } if (is_object($subsite)) { $subsiteID = $subsite->ID; } else { $subsiteID = $subsite; } Session::set('SubsiteID', (int) $subsiteID); // Set locale if (is_object($subsite) && $subsite->Language != '') { $locale = i18n::get_locale_from_lang($subsite->Language); if ($locale) { i18n::set_locale($locale); } } Permission::flush_permission_cache(); }
/** */ function translate($data, $form) { increase_time_limit_to(600); // Simple validation if (!isset($data['From']) || !$data['From']) { echo "Specify origin language."; exit; } if (!isset($data['To']) || !$data['To']) { echo "Specify destination language."; exit; } $data['From'] = i18n::get_locale_from_lang($data['From']); $data['To'] = i18n::get_locale_from_lang($data['To']); $locales = array_keys(i18n::get_locale_list()); if (!in_array($data['From'], $locales)) { echo "Origin language invalid."; exit; } if (!in_array($data['To'], $locales)) { echo "Destination language invalid."; exit; } if ($data['From'] == $data['To']) { echo "Origin and destination languages are the same."; exit; } $mangle = false; if (isset($data['Mangle']) && $data['Mangle']) { $mangle = true; } // We want to work off Draft, because that's what's visible in the CMS. Versioned::reading_stage('Stage'); Translatable::set_current_locale($data['From']); $pages = SiteTree::get(); // Remove the target locale's site. SiteTree::get()->filter('Locale', $data['To'])->removeAll(); foreach ($pages as $page) { echo "Now processing {$page->ID}<br/>\n"; // Start from the highest parent for each page - otherwise the parents are not translated properly. $stack = array(); $parent = $page; while ($parent && $parent->ID) { array_unshift($stack, $parent); $parent = $parent->Parent(); } // We will hit the same pages multiple times, but this is an easiest way to do it and it's just a tool. foreach ($stack as $stackPage) { $translation = $stackPage->getTranslation($data['To']); if ($translation && $translation->ID) { // Skip pages that have already been translated. echo "{$stackPage->ID}: exists, skipping.<br/>\n"; } else { $translation = $stackPage->createTranslation($data['To']); if ($mangle) { $this->fakeTranslation($translation); } $translation->write(); echo "{$stackPage->ID}: translated.<br/>\n"; } } } }
/** * Adds translatable languages * * @param mixed A list of languages, either as an array or argument list */ public static function set_langs() { $args = func_get_args(); if (empty($args)) { trigger_error("TranslatableDataObject::set_langs() called with no arguments.", E_USER_ERROR); } $langs = isset($args[0]) && is_array($args[0]) ? $args[0] : $args; foreach ($langs as $l) { if (!i18n::get_locale_from_lang($l)) { trigger_error("TranslatableDataObject::set_langs() -- Languages '{$l}' is not a valid language.", E_USER_ERROR); } self::$langs[$l] = $l; } }
public function collect($restrictToModules = null, $mergeWithExisting = true) { $clearUnused = $this->getClearUnused(); $glob = glob($this->basePath . '/*', GLOB_ONLYDIR); $modules = array_map(function ($item) { return basename($item); }, $glob); $themeFolders = array(); // A master string tables array (one master per module) $entitiesByModule = array(); // Scan themes foreach ($modules as $index => $module) { if ($module != 'themes') { continue; } else { $themes = scandir($this->basePath . "/themes"); if (count($themes)) { foreach ($themes as $theme) { if (is_dir($this->basePath . "/themes/" . $theme) && substr($theme, 0, 1) != '.' && is_dir($this->basePath . "/themes/" . $theme . "/templates")) { $themeFolders[] = 'themes/' . $theme; } } } $themesInd = $index; } } if (isset($themesInd)) { unset($modules[$themesInd]); } $modules = array_merge($modules, $themeFolders); foreach ($modules as $module) { if ($restrictToModules && !in_array($module, $restrictToModules)) { continue; } // Only search for calls in folder with a _config.php file (which means they are modules, including // themes folder) $isValidModuleFolder = is_dir("{$this->basePath}/{$module}") && is_file("{$this->basePath}/{$module}/_config.php") && substr($module, 0, 1) != '.' || substr($module, 0, 7) == 'themes/' && is_dir("{$this->basePath}/{$module}"); if (!$isValidModuleFolder) { continue; } // we store the master string tables $processedEntities = $this->processModule($module); if (isset($entitiesByModule[$module])) { $entitiesByModule[$module] = array_merge_recursive($entitiesByModule[$module], $processedEntities); } else { $entitiesByModule[$module] = $processedEntities; } // extract all entities for "foreign" modules (fourth argument) foreach ($entitiesByModule[$module] as $fullName => $spec) { if (isset($spec[2]) && $spec[2] && $spec[2] != $module) { $othermodule = $spec[2]; if (!isset($entitiesByModule[$othermodule])) { $entitiesByModule[$othermodule] = array(); } unset($spec[2]); $entitiesByModule[$othermodule][$fullName] = $spec; unset($entitiesByModule[$module][$fullName]); } } if ($mergeWithExisting) { $locale = $this->defaultLocale; // If we pass simple lang instead of locale, Zend_Translate will complain if (strlen($locale) == 2) { if (class_exists('Fluent')) { $fluentLocales = Fluent::locale_names(); foreach ($fluentLocales as $fluentLocale => $name) { if (substr($fluentLocale, 0, 2) == $locale) { $locale = $fluentLocale; } } } else { $locale = i18n::get_locale_from_lang($locale); } } $adapter = Injector::inst()->create('i18nRailsYamlAdapter'); $masterFile = "{$this->basePath}/{$module}/lang/" . $adapter->getFilenameForLocale($this->defaultLocale); if (!file_exists($masterFile)) { continue; } $adapter->addTranslation(array('content' => $masterFile, 'locale' => $this->defaultLocale, 'reload' => true, 'clear' => true)); //do not overwrite by interverting $messages = array_map(function ($v) { return array($v); }, $adapter->getMessages($this->defaultLocale)); $entitiesByModule[$module] = array_merge($entitiesByModule[$module], $messages); //clear by diffing if ($clearUnused) { $unusedEntities = array_diff(array_keys($messages), array_keys($processedEntities)); foreach ($unusedEntities as $unusedEntity) { if (strpos($unusedEntity, '.db_') !== false) { continue; } if (strpos($unusedEntity, '.has_one_') !== false) { continue; } if (strpos($unusedEntity, '.has_many_') !== false) { continue; } if (strpos($unusedEntity, '.many_many') !== false) { continue; } if (strpos($unusedEntity, '.belongs_many_many') !== false) { continue; } echo '<div style="color:red">Removed translations for ' . $unusedEntity . '</div>'; unset($entitiesByModule[$module][$unusedEntity]); } } } } // Restrict modules we update to just the specified ones (if any passed) if ($restrictToModules && count($restrictToModules)) { foreach (array_diff(array_keys($entitiesByModule), $restrictToModules) as $module) { unset($entitiesByModule[$module]); } } return $entitiesByModule; }
/** * @uses ModelAsController::getNestedController() * @return SS_HTTPResponse */ public function handleRequest(SS_HTTPRequest $request, DataModel $model) { $this->request = $request; $this->setDataModel($model); $this->pushCurrent(); //Get the local from the language param if (Config::inst()->get('MultilingualRootURLController', 'UseLocaleURL')) { if (Config::inst()->get('MultilingualRootURLController', 'UseDashLocale')) { //Language is missing a dash 404 if (strpos($request->param('Language'), '-') === false) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } $locale = explode('-', $request->param('Language')); $locale[1] = strtoupper($locale[1]); //Make sure that the language is all lowercase if ($request->param('Language') == implode('-', $locale)) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } $locale = implode('_', $locale); } else { $locale = $request->param('Language'); } } else { if (strpos($request->param('Language'), '_') !== false) { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } else { $locale = i18n::get_locale_from_lang($request->param('Language')); } } if (in_array($locale, Translatable::get_allowed_locales())) { //Set the current locale and remember it Cookie::set('language', $request->param('Language')); Translatable::set_current_locale($locale); i18n::set_locale($locale); } else { //Locale not found 404 if ($response = ErrorPage::response_for(404)) { return $response; } else { $this->httpError(404, 'The requested page could not be found.'); } return $this->response; } //Handle the home page for the language $urlSegment = $request->param('URLSegment'); if (empty($urlSegment)) { $controller = new MultilingualRootURLController(); $response = $controller->handleRequest($request, $model); $this->popCurrent(); return $response; } //Normal page request so handle that $response = parent::handleRequest($request, $model); $this->popCurrent(); return $response; }