feat: site languages, setup and site URL settings
This commit is contained in:
1 parent
0806733d5c
commit
d9158025d4
106 files changed
+10184
-56
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import { readFileSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { localizationMessages } from './localizationMessages'
|
||||
import { messages } from './messages'
|
||||
|
||||
const SOURCES = [
|
||||
'components/localization/AddLanguageDialog.vue',
|
||||
'components/localization/LanguageActionDialog.vue',
|
||||
'components/localization/LanguageRows.vue',
|
||||
'components/localization/LocaleDialog.vue',
|
||||
'components/localization/SocialLocaleDialog.vue',
|
||||
'composables/usePublicUrlPage.ts',
|
||||
'composables/useSiteLanguagesPage.ts',
|
||||
'lib/languageCopy.ts',
|
||||
'views/LanguageSetupView.vue',
|
||||
'views/PublicUrlView.vue',
|
||||
'views/SiteLanguagesView.vue',
|
||||
]
|
||||
|
||||
const SAME_IN_FRENCH = new Set(['Setup', 'Disable', 'Sites', '1 article', '{0} articles'])
|
||||
const LITERAL = /\bt\(\s*(?:'((?:\\.|[^'\\])*)'|"((?:\\.|[^"\\])*)")/g
|
||||
const NUMBERED = /\{\d+\}/g
|
||||
|
||||
function keysIn(source: string) {
|
||||
return [...source.matchAll(LITERAL)].map((match) =>
|
||||
(match[1] ?? match[2] ?? '').replace(/\\(['"\\])/g, '$1'),
|
||||
)
|
||||
}
|
||||
|
||||
describe('Localization messages', () => {
|
||||
const keys = SOURCES.flatMap((file) =>
|
||||
keysIn(readFileSync(join(import.meta.dirname, '..', file), 'utf8')).map((key) => ({
|
||||
file,
|
||||
key,
|
||||
})),
|
||||
)
|
||||
|
||||
it('finds the strings of the three pages', () => {
|
||||
expect(keys.length).toBeGreaterThan(120)
|
||||
})
|
||||
|
||||
it.each(keys.map(({ file, key }) => [file, key]))(
|
||||
'%s: "%s" has its own French entry',
|
||||
(_file, key) => {
|
||||
const french = (messages as Record<string, string>)[key as string]
|
||||
|
||||
expect(french).toMatch(/\S/)
|
||||
if (!SAME_IN_FRENCH.has(key as string)) {
|
||||
expect(french).not.toBe(key)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
it.each(Object.entries(localizationMessages))(
|
||||
'keeps the placeholders of "%s" in French',
|
||||
(english, french) => {
|
||||
expect([...french.matchAll(NUMBERED)].map((m) => m[0]).sort()).toEqual(
|
||||
[...english.matchAll(NUMBERED)].map((m) => m[0]).sort(),
|
||||
)
|
||||
expect(french.includes('{lang}')).toBe(english.includes('{lang}'))
|
||||
expect(french.includes('{slug}')).toBe(english.includes('{slug}'))
|
||||
},
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,217 @@
|
||||
export const localizationMessages = {
|
||||
Languages: 'Langues',
|
||||
'{0} · Languages': '{0} · Langues',
|
||||
'Back to Sites': 'Retour aux sites',
|
||||
'Content languages for {0}. Each article version is written in one language.':
|
||||
'Langues de contenu de {0}. Chaque version d’article est écrite dans une seule langue.',
|
||||
'Add language': 'Ajouter une langue',
|
||||
"Couldn't load languages": 'Impossible de charger les langues',
|
||||
'Only owners can change languages': 'Seuls les propriétaires peuvent modifier les langues',
|
||||
'You can see which languages are enabled, their social locale and how many versions each has. Ask an owner to change them.':
|
||||
'Vous pouvez voir quelles langues sont activées, leur locale sociale et le nombre de versions de chacune. Demandez à un propriétaire de les modifier.',
|
||||
'Set up languages': 'Configurer les langues',
|
||||
"Existing articles don't have a language yet. Confirm or change the language for each site.":
|
||||
'Les articles existants n’ont pas encore de langue. Confirmez ou changez la langue de chaque site.',
|
||||
'{0} is the default': '{0} est la langue par défaut',
|
||||
'Choose another default first, then disable {0}.':
|
||||
'Choisissez d’abord une autre langue par défaut, puis désactivez {0}.',
|
||||
'At least one language must stay enabled': 'Au moins une langue doit rester activée',
|
||||
'{0} needs a language for new articles.':
|
||||
'{0} a besoin d’une langue pour les nouveaux articles.',
|
||||
'Languages changed. Reload.': 'Langues modifiées. Rechargez.',
|
||||
"Another owner changed the languages for {0} while this page was open. Reload to see the current list. Your change wasn't applied.":
|
||||
'Un autre propriétaire a modifié les langues de {0} pendant que cette page était ouverte. Rechargez pour voir la liste actuelle. Votre modification n’a pas été appliquée.',
|
||||
"Couldn't change the default language": 'Impossible de changer la langue par défaut',
|
||||
"Couldn't remove {0}": 'Impossible de retirer {0}',
|
||||
'Nothing changed. {0} is still the default. Try again.':
|
||||
'Rien n’a changé. {0} reste la langue par défaut. Réessayez.',
|
||||
'Nothing changed. {0} is still listed. Try again.':
|
||||
'Rien n’a changé. {0} figure toujours dans la liste. Réessayez.',
|
||||
'{0} uses one language': '{0} utilise une seule langue',
|
||||
'New articles are written in {0}. Add a language to write translations and publish them separately.':
|
||||
'Les nouveaux articles sont rédigés en {0}. Ajoutez une langue pour écrire des traductions et les publier séparément.',
|
||||
'Social locale': 'Locale sociale',
|
||||
'Regional language kept: {0}': 'Langue régionale conservée : {0}',
|
||||
'Setup kept the full site locale, so the default content language is {0}, not plain {1}. The site locale still formats dates and numbers. Social locale: {2}, taken from the language code.':
|
||||
'La configuration a conservé la locale complète du site : la langue de contenu par défaut est donc {0}, et non {1} seul. La locale du site continue de formater les dates et les nombres. Locale sociale : {2}, tirée du code de langue.',
|
||||
'Disabling a language keeps its versions readable and editable, and published ones stay online. Drafts can be published again after you re-enable it. Social locale: Derived comes from the language code, Set is chosen by an owner, Not set leaves og:locale out.':
|
||||
'Désactiver une langue garde ses versions lisibles et modifiables, et les versions publiées restent en ligne. Les brouillons peuvent être publiés de nouveau après la réactivation. Locale sociale : Dérivée vient du code de langue, Définie est choisie par un propriétaire, Non définie omet og:locale.',
|
||||
'Public URL': 'URL publique',
|
||||
'{0} · Public URL': '{0} · URL publique',
|
||||
'Where {0} articles appear on your website. Used for canonical and alternate links.':
|
||||
'L’adresse où les articles de {0} apparaissent sur votre site web. Utilisée pour les liens canoniques et alternatifs.',
|
||||
'Only owners can change this': 'Seuls les propriétaires peuvent modifier ceci',
|
||||
'You can read the pattern. Ask an owner to change it.':
|
||||
'Vous pouvez lire le modèle. Demandez à un propriétaire de le modifier.',
|
||||
'Public URL not configured': 'URL publique non configurée',
|
||||
'Page, canonical and alternate addresses stay hidden until you add a pattern. Links by article ID still work.':
|
||||
'Les adresses de page, canoniques et alternatives restent masquées tant que vous n’ajoutez pas de modèle. Les liens par identifiant d’article fonctionnent toujours.',
|
||||
"Couldn't save languages": 'Impossible d’enregistrer les langues',
|
||||
'Nothing changed. Your selection is kept. Try again.':
|
||||
'Rien n’a changé. Votre sélection est conservée. Réessayez.',
|
||||
'Public URL pattern': 'Modèle d’URL publique',
|
||||
'Placeholders: {lang} is the language code, such as fr or pt-BR. {slug} is the article address in that language.':
|
||||
'Variables : {lang} est le code de langue, comme fr ou pt-BR. {slug} est l’adresse de l’article dans cette langue.',
|
||||
Setup: 'Configuration',
|
||||
'Site locale {0}': 'Locale du site {0}',
|
||||
'No site locale': 'Aucune locale de site',
|
||||
'Only the broader language {0} ({1}) is supported. Pages and the API will say {1}, not {2}.':
|
||||
'Seule la langue plus large {0} ({1}) est prise en charge. Les pages et l’API indiqueront {1}, et non {2}.',
|
||||
'Seeded from site locale {0}. Confirm or change.':
|
||||
'Issue de la locale du site {0}. Confirmez ou changez.',
|
||||
'Required before you can apply.': 'Obligatoire avant de pouvoir appliquer.',
|
||||
'Seeded from site locale {0}. The full locale is kept. Confirm or change it.':
|
||||
'Issue de la locale du site {0}. La locale complète est conservée. Confirmez ou changez-la.',
|
||||
'Set article languages': 'Définir les langues des articles',
|
||||
'Back to Languages': 'Retour aux langues',
|
||||
'Content languages for {0}.': 'Langues de contenu de {0}.',
|
||||
'Languages assigned': 'Langues attribuées',
|
||||
'Nothing was translated, and no articles were grouped.':
|
||||
'Rien n’a été traduit et aucun article n’a été regroupé.',
|
||||
'1 article now has a language. Nothing was translated, and no articles were grouped.':
|
||||
'1 article a maintenant une langue. Rien n’a été traduit et aucun article n’a été regroupé.',
|
||||
'{0} articles now have a language. Nothing was translated, and no articles were grouped.':
|
||||
'{0} articles ont maintenant une langue. Rien n’a été traduit et aucun article n’a été regroupé.',
|
||||
'Open Articles': 'Ouvrir les articles',
|
||||
'The update failed, so no article has a language yet. Your choices are kept. Try again. Running it twice is safe.':
|
||||
'La mise à jour a échoué : aucun article n’a encore de langue. Vos choix sont conservés. Réessayez. L’exécuter deux fois est sans risque.',
|
||||
'Setup is already running': 'La configuration est déjà en cours',
|
||||
"Another owner started it. Languages appear here when it finishes. Articles created meanwhile get each site's default language. Starting it again is safe: sites that already have a language are skipped.":
|
||||
'Un autre propriétaire l’a lancée. Les langues apparaissent ici quand elle se termine. Les articles créés entre-temps reçoivent la langue par défaut de leur site. La relancer est sans risque : les sites qui ont déjà une langue sont ignorés.',
|
||||
'Check again': 'Vérifier à nouveau',
|
||||
'Assigning languages': 'Attribution des langues',
|
||||
"Articles created while this runs get the site's default language.":
|
||||
'Les articles créés pendant l’opération reçoivent la langue par défaut du site.',
|
||||
'Choose a language for {0}': 'Choisissez une langue pour {0}',
|
||||
'{0} has no site locale, so there is nothing to start from. Choose the language its articles are written in.':
|
||||
'{0} n’a pas de locale de site, il n’y a donc rien dont partir. Choisissez la langue dans laquelle ses articles sont écrits.',
|
||||
'{0} have no site locale, so there is nothing to start from. Choose the language their articles are written in.':
|
||||
'{0} n’ont pas de locale de site, il n’y a donc rien dont partir. Choisissez la langue dans laquelle leurs articles sont écrits.',
|
||||
"This labels articles. It doesn't translate them.":
|
||||
'Cela étiquette les articles. Cela ne les traduit pas.',
|
||||
"Each existing article becomes the only version of its own article group. Each site's language starts from its locale with the region kept: pt-BR stays Portuguese (Brazil). Nothing is applied until you confirm.":
|
||||
'Chaque article existant devient la seule version de son propre groupe d’articles. La langue de chaque site part de sa locale en gardant la région : pt-BR reste portugais (Brésil). Rien n’est appliqué avant votre confirmation.',
|
||||
'Confirm the default language': 'Confirmer la langue par défaut',
|
||||
'{0} has no articles yet. New articles will be written in this language.':
|
||||
'{0} n’a pas encore d’articles. Les nouveaux articles seront rédigés dans cette langue.',
|
||||
'Default content language': 'Langue de contenu par défaut',
|
||||
'Choose a language': 'Choisir une langue',
|
||||
'Assigning…': 'Attribution…',
|
||||
'Language for {0}': 'Langue de {0}',
|
||||
'Confirm and assign to {0} articles': 'Confirmer et attribuer à {0} articles',
|
||||
'Counts are articles in 1 site.': 'Les totaux comptent les articles de 1 site.',
|
||||
'Counts are articles in {0} sites.': 'Les totaux comptent les articles de {0} sites.',
|
||||
'{0} · Disabled — re-enable instead': '{0} · Désactivée — réactivez-la plutôt',
|
||||
'{0} is already enabled for {1}.': '{0} est déjà activée pour {1}.',
|
||||
'Derived: {0}': 'Dérivée : {0}',
|
||||
'Not set': 'Non définie',
|
||||
"{0} isn't available": '{0} n’est pas disponible',
|
||||
"Only the broader language {0} ({1}) is supported. Pages and the API will say {1}, not {2}. Articles written in this language can't be told apart from other {0}.":
|
||||
'Seule la langue plus large {0} ({1}) est prise en charge. Les pages et l’API indiqueront {1}, et non {2}. Les articles écrits dans cette langue ne se distinguent pas des autres articles en {0}.',
|
||||
"Your change wasn't applied.": 'Votre modification n’a pas été appliquée.',
|
||||
'Add a language': 'Ajouter une langue',
|
||||
'Choose a language for {0}. Regional variants such as English (United Kingdom) are separate entries.':
|
||||
'Choisissez une langue pour {0}. Les variantes régionales comme l’anglais (Royaume-Uni) sont des entrées distinctes.',
|
||||
'Choose a language for {0}.': 'Choisissez une langue pour {0}.',
|
||||
'Add {0} ({1}) instead': 'Ajouter {0} ({1}) à la place',
|
||||
'Language code': 'Code de langue',
|
||||
'Used in the API and in page language metadata.':
|
||||
'Utilisé dans l’API et dans les métadonnées de langue des pages.',
|
||||
'Taken from the language code. For a code without a region, such as fr, an owner sets one or leaves it empty and og:locale is left out.':
|
||||
'Tirée du code de langue. Pour un code sans région, comme fr, un propriétaire en définit une ou la laisse vide et og:locale est omis.',
|
||||
"Existing versions keep their language, status and links. Public requests that name no language will resolve {0} where a published {0} version exists, and return not found where one doesn't. Requests that name a language aren't affected.":
|
||||
'Les versions existantes gardent leur langue, leur statut et leurs liens. Les requêtes publiques qui ne nomment aucune langue renverront {0} lorsqu’une version {0} publiée existe, et « introuvable » sinon. Les requêtes qui nomment une langue ne sont pas affectées.',
|
||||
'Make {0} the default language?': 'Faire de {0} la langue par défaut ?',
|
||||
'Disable {0}?': 'Désactiver {0} ?',
|
||||
'Re-enable {0}?': 'Réactiver {0} ?',
|
||||
"{0} can't be removed": '{0} ne peut pas être retirée',
|
||||
'New articles start in the default language.':
|
||||
'Les nouveaux articles commencent dans la langue par défaut.',
|
||||
"New articles start in the default language, and it is the first choice for each article's title in the list.":
|
||||
'Les nouveaux articles commencent dans la langue par défaut, qui est le premier choix pour le titre de chaque article dans la liste.',
|
||||
'Writers can create {0} versions again.':
|
||||
'Les rédacteurs peuvent de nouveau créer des versions en {0}.',
|
||||
'No article uses {0}.': 'Aucun article n’utilise {0}.',
|
||||
'No article uses {0}. You can add it again later.':
|
||||
'Aucun article n’utilise {0}. Vous pourrez la rajouter plus tard.',
|
||||
'Nothing changed. Try again.': 'Rien n’a changé. Réessayez.',
|
||||
"Couldn't re-enable {0}": 'Impossible de réactiver {0}',
|
||||
'Nothing changed. {0} is still disabled. Try again.':
|
||||
'Rien n’a changé. {0} est toujours désactivée. Réessayez.',
|
||||
'Make {0} default': 'Faire de {0} la langue par défaut',
|
||||
'Disable {0}': 'Désactiver {0}',
|
||||
'Re-enable {0}': 'Réactiver {0}',
|
||||
'No content changes': 'Aucun changement de contenu',
|
||||
'Nothing is deleted or unpublished': 'Rien n’est supprimé ni dépublié',
|
||||
Disable: 'Désactiver',
|
||||
'Edit social locale for {0}': 'Modifier la locale sociale de {0}',
|
||||
'Re-enable': 'Réactiver',
|
||||
'Use letters and one underscore, for example {0}.':
|
||||
'Utilisez des lettres et un seul tiret bas, par exemple {0}.',
|
||||
'Social locale for {0}': 'Locale sociale de {0}',
|
||||
'Used for og:locale on {0} pages. Leave it empty to omit the tag.':
|
||||
'Utilisée pour og:locale sur les pages en {0}. Laissez vide pour omettre la balise.',
|
||||
'Save social locale': 'Enregistrer la locale sociale',
|
||||
'Format: language_REGION, for example {0}. Letters only, one underscore.':
|
||||
'Format : langue_RÉGION, par exemple {0}. Lettres uniquement, un seul tiret bas.',
|
||||
'Derived from the language code': 'Dérivée du code de langue',
|
||||
'{0} gives {1}. Setting a value replaces the derived one.':
|
||||
'{0} donne {1}. Définir une valeur remplace la valeur dérivée.',
|
||||
'1 version · {0} published': '1 version · {0} publiée',
|
||||
'{0} versions · {1} published': '{0} versions · {1} publiées',
|
||||
'Set: {0}': 'Définie : {0}',
|
||||
'1 draft': '1 brouillon',
|
||||
'{0} drafts': '{0} brouillons',
|
||||
'{0} published': '{0} publiées',
|
||||
' and ': ' et ',
|
||||
'{0} is used by 1 version: {1}.': '{0} est utilisée par 1 version : {1}.',
|
||||
'{0} is used by {1} versions: {2}.': '{0} est utilisée par {1} versions : {2}.',
|
||||
'The published {0} version stays online.': 'La version {0} publiée reste en ligne.',
|
||||
'The {0} published {1} versions stay online.':
|
||||
'Les {0} versions {1} publiées restent en ligne.',
|
||||
'The version stays readable and editable.': 'La version reste lisible et modifiable.',
|
||||
'All {0} versions stay readable and editable.':
|
||||
'Les {0} versions restent lisibles et modifiables.',
|
||||
"The draft can't be published until you re-enable {0}.":
|
||||
'Le brouillon ne peut pas être publié avant la réactivation de {0}.',
|
||||
"The {0} drafts can't be published until you re-enable {1}.":
|
||||
'Les {0} brouillons ne peuvent pas être publiés avant la réactivation de {1}.',
|
||||
'Nobody can create new {0} versions.': 'Personne ne peut créer de nouvelles versions en {0}.',
|
||||
'Writers can create {0} versions again. Nothing else changes.':
|
||||
'Les rédacteurs peuvent de nouveau créer des versions en {0}. Rien d’autre ne change.',
|
||||
'Writers can create {0} versions again. The 1 existing {0} version stays as it is. Nothing else changes.':
|
||||
'Les rédacteurs peuvent de nouveau créer des versions en {0}. La version {0} existante reste telle quelle. Rien d’autre ne change.',
|
||||
'Writers can create {0} versions again. The {1} existing {0} versions stay as they are. Nothing else changes.':
|
||||
'Les rédacteurs peuvent de nouveau créer des versions en {0}. Les {1} versions {0} existantes restent telles quelles. Rien d’autre ne change.',
|
||||
'{0} is used by 1 version. Disable the language to keep it, or delete it first.':
|
||||
'{0} est utilisée par 1 version. Désactivez la langue pour la garder, ou supprimez-la d’abord.',
|
||||
'{0} is used by {1} versions. Disable the language to keep it, or delete it first.':
|
||||
'{0} est utilisée par {1} versions. Désactivez la langue pour les garder, ou supprimez-les d’abord.',
|
||||
'{0} is used by 1 version.': '{0} est utilisée par 1 version.',
|
||||
'{0} is used by {1} versions.': '{0} est utilisée par {1} versions.',
|
||||
'{0} added': '{0} ajoutée',
|
||||
'Writers can now create {0} versions.':
|
||||
'Les rédacteurs peuvent maintenant créer des versions en {0}.',
|
||||
'{0} re-enabled': '{0} réactivée',
|
||||
'Writers can create {0} versions again. Drafts can be published.':
|
||||
'Les rédacteurs peuvent de nouveau créer des versions en {0}. Les brouillons peuvent être publiés.',
|
||||
'Start with https:// or http://.': 'Commencez par https:// ou http://.',
|
||||
'Unknown placeholder {0}. Use {lang} and {slug}.':
|
||||
'Variable inconnue {0}. Utilisez {lang} et {slug}.',
|
||||
'Unknown placeholder. Use {lang} and {slug}.': 'Variable inconnue. Utilisez {lang} et {slug}.',
|
||||
'Remove spaces and characters that need encoding. Use letters, digits, - and _.':
|
||||
'Retirez les espaces et les caractères à encoder. Utilisez des lettres, des chiffres, - et _.',
|
||||
'Add {slug} so each article has its own address.':
|
||||
'Ajoutez {slug} pour que chaque article ait sa propre adresse.',
|
||||
'Preview with "{0}" in {1}': 'Aperçu avec « {0} » en {1}',
|
||||
'Public URL saved': 'URL publique enregistrée',
|
||||
'{0} pages now use this pattern.': 'Les pages de {0} utilisent maintenant ce modèle.',
|
||||
'List the content languages of a site: the default first, then the other enabled ones, then the disabled ones. Each carries its version and published counts and its social locale. Send the revision back when you change them. A site with no confirmed default answers needs_setup true and no languages.':
|
||||
'Liste les langues de contenu d’un site : la langue par défaut d’abord, puis les autres langues activées, puis les désactivées. Chacune porte son nombre de versions et de versions publiées, et sa locale sociale. Renvoyez la révision quand vous les modifiez. Un site sans langue par défaut confirmée répond needs_setup true et aucune langue.',
|
||||
'Replace the content languages of a site': 'Remplacer les langues de contenu d’un site',
|
||||
'Language setup · owner only': 'Configuration des langues · propriétaire uniquement',
|
||||
'Sites that still need a default language':
|
||||
'Sites qui ont encore besoin d’une langue par défaut',
|
||||
'Confirm the default language of every pending site':
|
||||
'Confirmer la langue par défaut de chaque site en attente',
|
||||
} as const
|
||||
@@ -1,4 +1,7 @@
|
||||
import { localizationMessages } from './localizationMessages'
|
||||
|
||||
export const messages = {
|
||||
...localizationMessages,
|
||||
'Not found': 'Introuvable',
|
||||
'Edit article': 'Modifier l’article',
|
||||
unselected: 'désélectionnée',
|
||||
|
||||
Reference in new issue
Block a user