i18n: translate hardcoded strings on project page and footer
Build and Deploy Verso / deploy (push) Successful in 17m39s
Build and Deploy Verso / deploy (push) Successful in 17m39s
- Card owner: "You" now goes through t('you') so it renders as
"Vous"/"Tu"/"Du" etc. instead of always "You"
- Relative dates (fromNow): moment.locale() is now set from the app
language so "2 days ago" becomes "il y a 2 jours" etc.
- Footer: "Built on", "Source code", "AGPL licence" are now translated
via t() with keys added to all locale files and extracted-translations
- New keys: built_on, source_code, agpl_licence (FR/DE/IT/ES translations
added manually)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -117,6 +117,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "",
|
||||
"aggregate_changed": "",
|
||||
"aggregate_to": "",
|
||||
"agpl_licence": "",
|
||||
"agree": "",
|
||||
"agree_with_the_terms": "",
|
||||
"ai_assist_in_overleaf_is_included_via_writefull_groups": "",
|
||||
@@ -228,6 +229,7 @@
|
||||
"breadcrumbs": "",
|
||||
"browser": "",
|
||||
"build_collection_of_most_used_references": "",
|
||||
"built_on": "",
|
||||
"bullet_list": "",
|
||||
"buy_licenses": "",
|
||||
"buy_more_licenses": "",
|
||||
@@ -1909,6 +1911,7 @@
|
||||
"sort_by": "",
|
||||
"sort_by_x": "",
|
||||
"sort_projects": "",
|
||||
"source_code": "",
|
||||
"speak": "",
|
||||
"speech_input_not_available": "",
|
||||
"spellcheck": "",
|
||||
|
||||
@@ -99,9 +99,11 @@ const ProjectCard = memo(function ProjectCard({
|
||||
}: {
|
||||
project: Project
|
||||
}) {
|
||||
const { t } = useTranslation()
|
||||
const { tags } = useProjectListContext()
|
||||
const variant = getFormatVariant(project.compiler, project.quartoFlavor)
|
||||
const ownerName = getOwnerName(project)
|
||||
const rawOwner = getOwnerName(project)
|
||||
const ownerName = rawOwner === 'You' ? t('you') : rawOwner
|
||||
const date = fromNowDate(project.lastUpdated)
|
||||
const initial = project.name.charAt(0).toUpperCase() || '?'
|
||||
const projectTags = tags
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
import OLRow from '@/shared/components/ol/ol-row'
|
||||
import LanguagePicker from '@/shared/components/language-picker'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
function FooterItemLi({
|
||||
text,
|
||||
@@ -41,6 +42,7 @@ function Separator() {
|
||||
}
|
||||
|
||||
function ThinFooter({ subdomainLang, leftItems, rightItems }: FooterMetadata) {
|
||||
const { t } = useTranslation()
|
||||
const showLanguagePicker = Boolean(
|
||||
subdomainLang && Object.keys(subdomainLang).length > 1
|
||||
)
|
||||
@@ -62,7 +64,7 @@ function ThinFooter({ subdomainLang, leftItems, rightItems }: FooterMetadata) {
|
||||
</li>
|
||||
<Separator />
|
||||
<li>
|
||||
Built on{' '}
|
||||
{t('built_on')}{' '}
|
||||
<a
|
||||
href="https://github.com/overleaf/overleaf"
|
||||
target="_blank"
|
||||
@@ -90,7 +92,7 @@ function ThinFooter({ subdomainLang, leftItems, rightItems }: FooterMetadata) {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
AGPL licence
|
||||
{t('agpl_licence')}
|
||||
</a>
|
||||
</li>
|
||||
<Separator />
|
||||
@@ -100,7 +102,7 @@ function ThinFooter({ subdomainLang, leftItems, rightItems }: FooterMetadata) {
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Source code
|
||||
{t('source_code')}
|
||||
</a>
|
||||
</li>
|
||||
{rightItems?.map(item => (
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
import moment from 'moment'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
// Set moment's display locale to match the app language so that
|
||||
// fromNow() returns "il y a 2 jours" rather than "2 days ago", etc.
|
||||
const _lang = getMeta('ol-i18n')?.currentLangCode ?? 'en'
|
||||
if (_lang !== 'en') {
|
||||
import(`moment/locale/${_lang}`)
|
||||
.then(() => { moment.locale(_lang) })
|
||||
.catch(() => { /* fall back to English */ })
|
||||
}
|
||||
|
||||
export function formatDate(date: moment.MomentInput, format?: string) {
|
||||
if (!date) return 'N/A'
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "Danach berechnen wir dir jährlich am __date__ __totalAmount__ (__subtotalAmount__ + __taxAmount__ Steuern), falls du nicht kündigst.",
|
||||
"aggregate_changed": "Geändert",
|
||||
"aggregate_to": "zu",
|
||||
"agpl_licence": "AGPL-Lizenz",
|
||||
"agree": "Zustimmen",
|
||||
"agree_with_the_terms": "Ich stimme den Verso Bedingungen zu",
|
||||
"ai_allowance": "KI-Zulage",
|
||||
@@ -311,6 +312,7 @@
|
||||
"browser": "Browser",
|
||||
"build_collection_of_most_used_references": "Erstellen Sie in der Bibliothek eine Sammlung Ihrer am häufigsten verwendeten Referenzen, damit Sie sie problemlos zu jedem Projekt hinzufügen können.",
|
||||
"built_in": "Eigener",
|
||||
"built_on": "Basiert auf",
|
||||
"bullet_list": "Bullet-Liste",
|
||||
"buy_add_on": "Add-on kaufen",
|
||||
"buy_licenses": "Lizenzen kaufen",
|
||||
@@ -2495,6 +2497,7 @@
|
||||
"sort_by_x": "Nach __x__ sortieren",
|
||||
"sort_projects": "Projekte sortieren",
|
||||
"source": "Quelldateien",
|
||||
"source_code": "Quellcode",
|
||||
"speak": "Sprich",
|
||||
"speech_input_not_available": "Die Spracheingabe ist in diesem Browser noch nicht verfügbar",
|
||||
"spellcheck": "Rechtschreibprüfung",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "After that, we’ll bill you __totalAmount__ (__subtotalAmount__ + __taxAmount__ tax) annually on __date__, unless you cancel.",
|
||||
"aggregate_changed": "Changed",
|
||||
"aggregate_to": "to",
|
||||
"agpl_licence": "AGPL licence",
|
||||
"agree": "Agree",
|
||||
"agree_with_the_terms": "I agree with the Verso terms",
|
||||
"ai_allowance": "AI allowance",
|
||||
@@ -305,6 +306,7 @@
|
||||
"browser": "Browser",
|
||||
"build_collection_of_most_used_references": "Build a collection of your most-used references in the Library, so you can easily add them to any project.",
|
||||
"built_in": "Built-In",
|
||||
"built_on": "Built on",
|
||||
"bullet_list": "Bullet list",
|
||||
"buy_add_on": "Buy add-on",
|
||||
"buy_licenses": "Buy licenses",
|
||||
@@ -2474,6 +2476,7 @@
|
||||
"sort_by_x": "Sort by __x__",
|
||||
"sort_projects": "Sort projects",
|
||||
"source": "Source",
|
||||
"source_code": "Source code",
|
||||
"speak": "Speak",
|
||||
"speech_input_not_available": "Speech input is not yet available in this browser",
|
||||
"spellcheck": "Spellcheck",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "Después de eso, le facturaremos __totalAmount__ (__subtotalAmount__ + __taxAmount__ impuestos) anualmente el __date__, a menos que cancele.",
|
||||
"aggregate_changed": "Cambiado",
|
||||
"aggregate_to": "a",
|
||||
"agpl_licence": "Licencia AGPL",
|
||||
"agree": "De acuerdo",
|
||||
"agree_with_the_terms": "Estoy de acuerdo con los términos Verso",
|
||||
"ai_allowance": "subsidio de IA",
|
||||
@@ -306,6 +307,7 @@
|
||||
"browser": "Navegador",
|
||||
"build_collection_of_most_used_references": "Cree una colección de sus referencias más utilizadas en la Biblioteca, para que pueda agregarlas fácilmente a cualquier proyecto.",
|
||||
"built_in": "Integrado",
|
||||
"built_on": "Desarrollado con",
|
||||
"bullet_list": "lista de viñetas",
|
||||
"buy_add_on": "Comprar complemento",
|
||||
"buy_licenses": "Comprar licencias",
|
||||
@@ -2475,6 +2477,7 @@
|
||||
"sort_by_x": "Ordenar por __x__",
|
||||
"sort_projects": "Ordenar proyectos",
|
||||
"source": "Fuente",
|
||||
"source_code": "Código fuente",
|
||||
"speak": "hablar",
|
||||
"speech_input_not_available": "La entrada de voz aún no está disponible en este navegador",
|
||||
"spellcheck": "corrector ortográfico",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "Après cela, nous vous facturerons __totalAmount__ (__subtotalAmount__ + __taxAmount__ taxe) annuellement le __date__, sauf si vous annulez.",
|
||||
"aggregate_changed": "Modification de",
|
||||
"aggregate_to": "en",
|
||||
"agpl_licence": "Licence AGPL",
|
||||
"agree": "D'accord",
|
||||
"agree_with_the_terms": "J'accepte les conditions d'utilisation de Verso",
|
||||
"ai_allowance": "Allocation IA",
|
||||
@@ -306,6 +307,7 @@
|
||||
"browser": "Navigateur",
|
||||
"build_collection_of_most_used_references": "Créez une collection de vos références les plus utilisées dans la bibliothèque, afin de pouvoir les ajouter facilement à n'importe quel projet.",
|
||||
"built_in": "Intégré",
|
||||
"built_on": "Construit sur",
|
||||
"bullet_list": "Liste à puces",
|
||||
"buy_add_on": "Acheter un module complémentaire",
|
||||
"buy_licenses": "Acheter des licences",
|
||||
@@ -2479,6 +2481,7 @@
|
||||
"sort_by_x": "Trier par __x__",
|
||||
"sort_projects": "Trier les projets",
|
||||
"source": "Code source",
|
||||
"source_code": "Code source",
|
||||
"speak": "Parler",
|
||||
"speech_input_not_available": "La saisie vocale n'est pas encore disponible dans ce navigateur",
|
||||
"spellcheck": "Vérification orthographique",
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
"after_that_well_bill_you_x_total_y_subtotal_z_tax_annually_on_date_unless_you_cancel": "Successivamente, ti addebiteremo __totalAmount__ (__subtotalAmount__ + __taxAmount__ tasse) annualmente il __date__, a meno che tu non annulli l'abbonamento.",
|
||||
"aggregate_changed": "Cambiato",
|
||||
"aggregate_to": "a",
|
||||
"agpl_licence": "Licenza AGPL",
|
||||
"agree": "D'accordo",
|
||||
"agree_with_the_terms": "Sono d'accordo con i termini di Verso",
|
||||
"ai_allowance": "Indennità AI",
|
||||
@@ -305,6 +306,7 @@
|
||||
"browser": "Navigatore",
|
||||
"build_collection_of_most_used_references": "Crea una raccolta dei riferimenti più utilizzati nella Libreria, in modo da poterli aggiungere facilmente a qualsiasi progetto.",
|
||||
"built_in": "Built-In",
|
||||
"built_on": "Basato su",
|
||||
"bullet_list": "Elenco puntato",
|
||||
"buy_add_on": "Acquista il componente aggiuntivo",
|
||||
"buy_licenses": "Acquista licenze",
|
||||
@@ -2474,6 +2476,7 @@
|
||||
"sort_by_x": "Ordina per __x__",
|
||||
"sort_projects": "Ordina progetti",
|
||||
"source": "Sorgente",
|
||||
"source_code": "Codice sorgente",
|
||||
"speak": "Parla",
|
||||
"speech_input_not_available": "L'input vocale non è ancora disponibile in questo browser",
|
||||
"spellcheck": "Controllo ortografico",
|
||||
|
||||
Reference in New Issue
Block a user