}> */ private const LOCALES = [ ['fr', 'French', 'Français', 'ltr', ['one', 'many', 'other']], ['fr-FR', 'French (France)', 'Français (France)', 'ltr', ['one', 'many', 'other']], ['fr-CA', 'French (Canada)', 'Français (Canada)', 'ltr', ['one', 'many', 'other']], ['en', 'English', 'English', 'ltr', ['one', 'other']], ['en-GB', 'English (UK)', 'English (UK)', 'ltr', ['one', 'other']], ['en-US', 'English (US)', 'English (US)', 'ltr', ['one', 'other']], ['es-ES', 'Spanish (Spain)', 'Español (España)', 'ltr', ['one', 'many', 'other']], ['de-DE', 'German (Germany)', 'Deutsch (Deutschland)', 'ltr', ['one', 'other']], ['it-IT', 'Italian (Italy)', 'Italiano (Italia)', 'ltr', ['one', 'many', 'other']], ['pt-BR', 'Portuguese (Brazil)', 'Português (Brasil)', 'ltr', ['one', 'many', 'other']], ['pt-PT', 'Portuguese (Portugal)', 'Português (Portugal)', 'ltr', ['one', 'many', 'other']], ['nl-NL', 'Dutch (Netherlands)', 'Nederlands', 'ltr', ['one', 'other']], // L'arabe est présent expressément : six formes et sens d'écriture // inversé, c'est la langue qui casse les éditeurs mal conçus. ['ar', 'Arabic', 'العربية', 'rtl', ['zero', 'one', 'two', 'few', 'many', 'other']], ['he', 'Hebrew', 'עברית', 'rtl', ['one', 'two', 'many', 'other']], ['pl-PL', 'Polish (Poland)', 'Polski', 'ltr', ['one', 'few', 'many', 'other']], ['ru-RU', 'Russian (Russia)', 'Русский', 'ltr', ['one', 'few', 'many', 'other']], ['ja-JP', 'Japanese (Japan)', '日本語', 'ltr', ['other']], ['zh-CN', 'Chinese (Simplified)', '简体中文', 'ltr', ['other']], ]; public function getDescription(): string { return 'Installe le référentiel de langues : sans lui, aucun projet ne peut être créé.'; } public function up(Schema $schema): void { foreach (self::LOCALES as [$code, $name, $nativeName, $direction, $plurals]) { $this->addSql( 'INSERT IGNORE INTO locale (code, name, native_name, direction, plural_categories) ' .'VALUES (:code, :name, :nativeName, :direction, :plurals)', [ 'code' => $code, 'name' => $name, 'nativeName' => $nativeName, 'direction' => $direction, 'plurals' => json_encode($plurals, \JSON_THROW_ON_ERROR), ], ); } // Chaînes de repli : une traduction manquante en fr-CA retombe sur fr // avant de retomber sur la langue source du projet. foreach ([['fr-FR', 'fr'], ['fr-CA', 'fr'], ['en-GB', 'en'], ['en-US', 'en'], ['pt-PT', 'pt-BR']] as [$child, $parent]) { $this->addSql( 'UPDATE locale c JOIN locale p ON p.code = :parent SET c.fallback_locale_id = p.id ' .'WHERE c.code = :child AND c.fallback_locale_id IS NULL', ['child' => $child, 'parent' => $parent], ); } } public function down(Schema $schema): void { // On ne supprime que les langues qu'AUCUN projet n'utilise. Effacer une // langue référencée casserait les traductions existantes en cascade, ce // qu'un retour en arrière de migration ne doit jamais faire. $this->addSql('UPDATE locale SET fallback_locale_id = NULL'); $this->addSql( 'DELETE FROM locale WHERE code IN (:codes) ' .'AND id NOT IN (SELECT locale_id FROM project_locale) ' .'AND id NOT IN (SELECT source_locale_id FROM project)', ['codes' => array_column(self::LOCALES, 0)], ['codes' => \Doctrine\DBAL\ArrayParameterType::STRING], ); } }