Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [1.9.20] - 2026-09-24

### Added

- Turkish (`tr`) interface language: full interface translation, Turkish as a native-language option at registration and in Settings, and Turkish verification, password reset, welcome, and account deletion emails. The dashboard announcement keeps its existing ten locales and falls back to English for Turkish users.

### Fixed

- Onboarding learning goals now name the selected language in all ten interface languages, with natural wording and a safe display fallback for unrecognized language codes.
Expand Down
7 changes: 7 additions & 0 deletions backend/app/routers/lessons.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@
"good_pronunciation": "Pronuntie buna!",
"target_phrase": "Fraza tinta a fost: {answer}",
},
"tr": {
"correct": "Doğru!",
"correct_answer": "Doğru cevap: {answer}",
"free_write_unavailable": "Yazılı cevap şu anda değerlendirilemedi.",
"good_pronunciation": "Telaffuzunuz iyi!",
"target_phrase": "Hedef ifade şuydu: {answer}",
},
}


Expand Down
1 change: 1 addition & 0 deletions backend/app/schemas/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"nl",
"pl",
"ro",
"tr",
}


Expand Down
2 changes: 2 additions & 0 deletions backend/app/schemas/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def validate_password_strength(v: str) -> str:
"nl",
"pl",
"ro",
"tr",
}

SUPPORTED_TARGET_LANGUAGES: set[str] = {
Expand Down Expand Up @@ -65,6 +66,7 @@ def get_available_languages() -> list[str]:
"nl",
"ro",
"ru",
"tr",
}

VALID_LEARNING_GOALS: set[str] = {
Expand Down
66 changes: 66 additions & 0 deletions backend/app/services/email_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,14 @@ def _get_mail_config() -> ConnectionConfig:
"link_fallback": "\u0415\u0441\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0438 \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440:",
"footer": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u044d\u0442\u043e\u0442 \u0430\u043a\u043a\u0430\u0443\u043d\u0442, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u044d\u0442\u043e \u043f\u0438\u0441\u044c\u043c\u043e.",
},
"tr": {
"greeting": "Merhaba {name},",
"subject": "FreeLingo hesab\u0131n\u0131z\u0131 do\u011frulay\u0131n",
"body": "FreeLingo hesab\u0131n\u0131z\u0131 olu\u015fturdu\u011funuz i\u00e7in te\u015fekk\u00fcr ederiz.<br />L\u00fctfen a\u015fa\u011f\u0131daki d\u00fc\u011fmeye t\u0131klayarak e-posta adresinizi do\u011frulay\u0131n. Bu ba\u011flant\u0131 <strong>24 saat</strong> ge\u00e7erlidir.",
"button": "Hesab\u0131m\u0131 do\u011frula",
"link_fallback": "D\u00fc\u011fme \u00e7al\u0131\u015fmazsa bu ba\u011flant\u0131y\u0131 kopyalay\u0131p taray\u0131c\u0131n\u0131za yap\u0131\u015ft\u0131r\u0131n:",
"footer": "Bu hesab\u0131 siz olu\u015fturmad\u0131ysan\u0131z bu e-postay\u0131 yok sayabilirsiniz.",
},
}

_RESET_I18N: dict[str, dict[str, str]] = {
Expand Down Expand Up @@ -205,6 +213,14 @@ def _get_mail_config() -> ConnectionConfig:
"link_fallback": "\u0415\u0441\u043b\u0438 \u043a\u043d\u043e\u043f\u043a\u0430 \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441\u043a\u043e\u043f\u0438\u0440\u0443\u0439\u0442\u0435 \u0438 \u0432\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440:",
"footer": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0438 \u0441\u0431\u0440\u043e\u0441, \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0433\u043d\u043e\u0440\u0438\u0440\u0443\u0439\u0442\u0435 \u044d\u0442\u043e \u043f\u0438\u0441\u044c\u043c\u043e.",
},
"tr": {
"greeting": "Merhaba {name},",
"subject": "FreeLingo parolan\u0131z\u0131 s\u0131f\u0131rlay\u0131n",
"body": "FreeLingo hesab\u0131n\u0131z\u0131n parolas\u0131n\u0131 s\u0131f\u0131rlama iste\u011fi ald\u0131k.<br />Yeni bir parola olu\u015fturmak i\u00e7in a\u015fa\u011f\u0131daki d\u00fc\u011fmeye t\u0131klay\u0131n. Bu ba\u011flant\u0131 <strong>1 saat</strong> ge\u00e7erlidir.",
"button": "Parolam\u0131 s\u0131f\u0131rla",
"link_fallback": "D\u00fc\u011fme \u00e7al\u0131\u015fmazsa bu ba\u011flant\u0131y\u0131 kopyalay\u0131p taray\u0131c\u0131n\u0131za yap\u0131\u015ft\u0131r\u0131n:",
"footer": "Parola s\u0131f\u0131rlama iste\u011finde bulunmad\u0131ysan\u0131z bu e-postay\u0131 g\u00fcvenle yok sayabilirsiniz.",
},
}

_WELCOME_I18N: dict[str, dict[str, str]] = {
Expand Down Expand Up @@ -308,6 +324,16 @@ def _get_mail_config() -> ConnectionConfig:
"button": "\u041f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f",
"footer": "\u0423\u0441\u043f\u0435\u0445\u043e\u0432 \u0432 \u043e\u0431\u0443\u0447\u0435\u043d\u0438\u0438!",
},
"tr": {
"subject": "FreeLingo'ya ho\u015f geldiniz!",
"greeting": "Merhaba {name},",
"body": "Hesab\u0131n\u0131z haz\u0131r. Ba\u015flamak i\u00e7in \u015funlar\u0131 yapabilirsiniz:",
"step1": "<strong>Seviye Tespitine</strong> girin \u2014 mevcut seviyenizi (A1\u2013C2), g\u00fc\u00e7l\u00fc ve zay\u0131f y\u00f6nlerinizi belirler.",
"step2": "<strong>\u00c7al\u0131\u015fma Plan\u0131n\u0131z\u0131</strong> olu\u015fturun \u2014 seviyenize ve hedeflerinize g\u00f6re haz\u0131rlanm\u0131\u015f haftal\u0131k bir program.",
"step3": "\u0130lk g\u00fcnl\u00fck dersinizi tamamlay\u0131n ve serinizi olu\u015fturmaya ba\u015flay\u0131n.",
"button": "Panoma git",
"footer": "\u0130yi \u00e7al\u0131\u015fmalar!",
},
}


Expand Down Expand Up @@ -372,6 +398,12 @@ def _get_mail_config() -> ConnectionConfig:
"body": "\u0412\u0430\u0448 \u0430\u043a\u043a\u0430\u0443\u043d\u0442 FreeLingo \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0443\u0434\u0430\u043b\u0451\u043d. \u0412\u0441\u0435 \u0432\u0430\u0448\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0431\u044b\u043b\u0438 \u043d\u0430\u0432\u0441\u0435\u0433\u0434\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u044b \u0441 \u043d\u0430\u0448\u0438\u0445 \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u0432.",
"footer": "\u0415\u0441\u043b\u0438 \u0432\u044b \u043d\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435, \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0441\u0432\u044f\u0436\u0438\u0442\u0435\u0441\u044c \u0441 \u043d\u0430\u043c\u0438.",
},
"tr": {
"subject": "FreeLingo hesab\u0131n\u0131z silindi",
"greeting": "Merhaba {name},",
"body": "FreeLingo hesab\u0131n\u0131z ba\u015far\u0131yla silindi. T\u00fcm verileriniz sunucular\u0131m\u0131zdan kal\u0131c\u0131 olarak kald\u0131r\u0131ld\u0131.",
"footer": "Bu silme i\u015flemini siz istemediyseniz l\u00fctfen hemen bizimle ileti\u015fime ge\u00e7in.",
},
}

_CONTACT_I18N: dict[str, dict[str, str]] = {
Expand Down Expand Up @@ -465,6 +497,15 @@ def _get_mail_config() -> ConnectionConfig:
"message_label": "Сообщение",
"footer": "Отправлено через контактную форму FreeLingo",
},
"tr": {
"email_title": "İletişim formu mesajı",
"subject_prefix": "[FreeLingo İletişim]",
"logo": "FreeLingo: İletişim Formu",
"from_label": "Gönderen",
"subject_label": "Konu",
"message_label": "Mesaj",
"footer": "FreeLingo iletişim formu aracılığıyla gönderildi",
},
}

_FEEDBACK_I18N: dict[str, dict[str, str]] = {
Expand Down Expand Up @@ -598,6 +639,19 @@ def _get_mail_config() -> ConnectionConfig:
"cta": "Открыть в панели администратора",
"footer": "Доска отзывов FreeLingo",
},
"tr": {
"email_title": "Yeni geri bildirim gönderildi",
"logo": "FreeLingo: Yeni Geri Bildirim",
"feature_label": "Özellik isteği",
"bug_label": "Hata bildirimi",
"feature_subject_prefix": "[Özellik İsteği]",
"bug_subject_prefix": "[Hata Bildirimi]",
"author_label": "Gönderen",
"title_label": "Başlık",
"description_label": "Açıklama",
"cta": "Yönetim panelinde görüntüle",
"footer": "FreeLingo geri bildirim panosu",
},
}

_REVIEW_I18N: dict[str, dict[str, str]] = {
Expand Down Expand Up @@ -721,6 +775,18 @@ def _get_mail_config() -> ConnectionConfig:
"cta": "Открыть в панели администратора",
"footer": "Модерация отзывов FreeLingo",
},
"tr": {
"email_title": "Yeni yorum gönderildi",
"subject_prefix": "[Yeni Yorum]",
"logo": "FreeLingo: Yeni Yorum",
"author_label": "Gönderen",
"rating_label": "Puan",
"language_label": "Öğrenilen dil",
"comment_label": "Yorum",
"empty_comment": "Yorum yazılmadı.",
"cta": "Yönetim panelinde görüntüle",
"footer": "FreeLingo yorum moderasyonu",
},
}


Expand Down
16 changes: 16 additions & 0 deletions backend/app/services/language_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
"nl": "Spraaksessie",
"ro": "Sesiune vocală",
"ru": "Голосовая сессия",
"tr": "Sesli oturum",
}

_NATIVE_LANGUAGE_NAMES: dict[str, str] = {
Expand All @@ -148,6 +149,7 @@
"nl": "Dutch",
"ro": "Romanian",
"ru": "Russian",
"tr": "Turkish",
}

_MONTH_NAMES: dict[str, list[str]] = {
Expand Down Expand Up @@ -277,6 +279,20 @@
"ноября",
"декабря",
],
"tr": [
"Ocak",
"Şubat",
"Mart",
"Nisan",
"Mayıs",
"Haziran",
"Temmuz",
"Ağustos",
"Eylül",
"Ekim",
"Kasım",
"Aralık",
],
}


Expand Down
12 changes: 11 additions & 1 deletion backend/tests/test_conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,11 +577,21 @@ def test_voice_session_title_russian() -> None:
assert " de " not in date_part


def test_voice_session_title_turkish() -> None:
"""Turkish uses its own label and plain 'D Month YYYY' format."""
from app.services.language_helpers import voice_session_title

title = voice_session_title("tr")
assert title.startswith("Sesli oturum — ")
date_part = title.split(" — ", 1)[1]
assert " de " not in date_part


def test_voice_session_title_all_supported_languages_produce_nonempty() -> None:
"""Every supported native language must produce a non-empty title."""
from app.services.language_helpers import voice_session_title

supported = ["es", "fr", "pt", "de", "it", "pl", "nl", "ro", "ru"]
supported = ["es", "fr", "pt", "de", "it", "pl", "nl", "ro", "ru", "tr"]
for lang in supported:
title = voice_session_title(lang)
assert title.strip(), f"Empty title for language '{lang}'"
Expand Down
1 change: 1 addition & 0 deletions frontend/src/app/(app)/admin/users/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const LANGUAGES = [
'nl',
'ro',
'ru',
'tr',
] as const

const PAGE_SIZE = 10
Expand Down
1 change: 1 addition & 0 deletions frontend/src/app/(auth)/register/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const LANGUAGES = [
'nl',
'ro',
'ru',
'tr',
] as const

type SelectedPlan = 'monthly' | 'yearly'
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export default async function RootLayout({
<script dangerouslySetInnerHTML={{ __html: themeScript }} />
<script
dangerouslySetInnerHTML={{
__html: `(function(){if(document.cookie.indexOf('LOCALE_DETECTED=')!==-1)return;var m=document.cookie.match(/(^| )NEXT_LOCALE=([^;]+)/);var cl=m?m[2]:null;var bl=(navigator.language||'').split('-')[0].toLowerCase();var s=['es','fr','pt','de','it','pl','nl','ro','ru'];document.cookie='LOCALE_DETECTED=1;path=/;max-age=31536000;SameSite=Lax';if(bl!=='en'&&s.indexOf(bl)!==-1&&cl!==bl){document.cookie='NEXT_LOCALE='+bl+';path=/;max-age=31536000;SameSite=Lax';location.reload()}})();`,
__html: `(function(){if(document.cookie.indexOf('LOCALE_DETECTED=')!==-1)return;var m=document.cookie.match(/(^| )NEXT_LOCALE=([^;]+)/);var cl=m?m[2]:null;var bl=(navigator.language||'').split('-')[0].toLowerCase();var s=['es','fr','pt','de','it','pl','nl','ro','ru','tr'];document.cookie='LOCALE_DETECTED=1;path=/;max-age=31536000;SameSite=Lax';if(bl!=='en'&&s.indexOf(bl)!==-1&&cl!==bl){document.cookie='NEXT_LOCALE='+bl+';path=/;max-age=31536000;SameSite=Lax';location.reload()}})();`,
}}
/>
{process.env.NEXT_PUBLIC_UMAMI_WEBSITE_ID && (
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/settings/ProfileSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const LANGUAGES = [
'nl',
'ro',
'ru',
'tr',
] as const

function resizeImage(file: File, maxPx: number): Promise<Blob> {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lib/locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export const SUPPORTED_LOCALES = [
'nl',
'ro',
'ru',
'tr',
] as const

export type Locale = (typeof SUPPORTED_LOCALES)[number]
2 changes: 1 addition & 1 deletion frontend/src/lib/target-languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export function getTargetLanguageTextClass(code: string): string {

export const DEFAULT_TARGET_LANGUAGE = 'en-GB'

const LOCALES_CAPITALIZE_LANGUAGE = new Set(['en', 'de', 'nl'])
const LOCALES_CAPITALIZE_LANGUAGE = new Set(['en', 'de', 'nl', 'tr'])

export function formatLanguageName(name: string, locale: string): string {
const lang = locale.split('-')[0]
Expand Down
4 changes: 3 additions & 1 deletion frontend/tests/app/onboarding-goals-subtitle.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import pl from '../../../messages/pl.json'
import pt from '../../../messages/pt.json'
import ro from '../../../messages/ro.json'
import ru from '../../../messages/ru.json'
import tr from '../../../messages/tr.json'

const { searchParams, apiFetch } = vi.hoisted(() => ({
searchParams: new URLSearchParams(),
Expand All @@ -31,7 +32,7 @@ vi.mock('@/lib/api', () => ({ apiFetch }))

import OnboardingPage from '@/app/(auth)/onboarding/page'

const catalogs = { de, en, es, fr, it: itMessages, nl, pl, pt, ro, ru }
const catalogs = { de, en, es, fr, it: itMessages, nl, pl, pt, ro, ru, tr }
type Locale = keyof typeof catalogs

const spanishSubtitles: Record<Locale, string> = {
Expand All @@ -45,6 +46,7 @@ const spanishSubtitles: Record<Locale, string> = {
pt: 'Idioma: espanhol. Para que você quer usá-lo? Selecione todos os objetivos que se aplicam.',
ro: 'Limbă: spaniolă. Pentru ce vrei să o folosești? Selectează toate obiectivele care ți se potrivesc.',
ru: 'Язык: испанский. Для чего ты хочешь его использовать? Выбери все подходящие цели.',
tr: 'Dil: İspanyolca. Bu dili ne için kullanmak istiyorsunuz? Uygun olanların hepsini seçin.',
}

const onIntlError = vi.fn()
Expand Down
2 changes: 2 additions & 0 deletions frontend/tests/components/ProfileSection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,7 @@ describe('ProfileSection', () => {
expect(options).toContain('nl')
expect(options).toContain('ro')
expect(options).toContain('ru')
expect(options).toContain('tr')
})

it('renders all ui locale options', () => {
Expand All @@ -820,6 +821,7 @@ describe('ProfileSection', () => {
expect(options).toContain('nl')
expect(options).toContain('ro')
expect(options).toContain('ru')
expect(options).toContain('tr')
})

// ── Avatar upload buttons ───────────────────────────────────
Expand Down
3 changes: 2 additions & 1 deletion frontend/tests/i18n/admin-messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import pl from '../../../messages/pl.json'
import pt from '../../../messages/pt.json'
import ro from '../../../messages/ro.json'
import ru from '../../../messages/ru.json'
import tr from '../../../messages/tr.json'

const locales = { de, es, fr, it: itMessages, nl, pl, pt, ro, ru }
const locales = { de, es, fr, it: itMessages, nl, pl, pt, ro, ru, tr }

describe('admin i18n messages', () => {
it('keeps admin namespace keys in sync across locales', () => {
Expand Down
1 change: 1 addition & 0 deletions messages/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Niederländisch",
"ro": "Rumänisch",
"ru": "Russisch",
"tr": "Türkisch",
"myLanguages": "Meine Sprachen",
"addLanguage": "Sprache hinzufügen",
"selectLanguage": "Wähle die Sprache, die du lernen möchtest",
Expand Down
1 change: 1 addition & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Dutch",
"ro": "Romanian",
"ru": "Russian",
"tr": "Turkish",
"myLanguages": "My Languages",
"addLanguage": "Add new language",
"selectLanguage": "Select the language you want to learn",
Expand Down
1 change: 1 addition & 0 deletions messages/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Neerlandés",
"ro": "Rumano",
"ru": "Ruso",
"tr": "Turco",
"myLanguages": "Mis idiomas",
"addLanguage": "Añadir idioma",
"selectLanguage": "Selecciona el idioma que quieres aprender",
Expand Down
1 change: 1 addition & 0 deletions messages/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Néerlandais",
"ro": "Roumain",
"ru": "Russe",
"tr": "Turc",
"myLanguages": "Mes langues",
"addLanguage": "Ajouter une langue",
"selectLanguage": "Choisissez la langue que vous voulez apprendre",
Expand Down
1 change: 1 addition & 0 deletions messages/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Olandese",
"ro": "Rumeno",
"ru": "Russo",
"tr": "Turco",
"myLanguages": "Le mie lingue",
"addLanguage": "Aggiungi lingua",
"selectLanguage": "Seleziona la lingua che vuoi imparare",
Expand Down
1 change: 1 addition & 0 deletions messages/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Nederlands",
"ro": "Roemeens",
"ru": "Russisch",
"tr": "Turks",
"myLanguages": "Mijn talen",
"addLanguage": "Taal toevoegen",
"selectLanguage": "Kies de taal die je wilt leren",
Expand Down
1 change: 1 addition & 0 deletions messages/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Niderlandzki",
"ro": "Rumuński",
"ru": "Rosyjski",
"tr": "Turecki",
"myLanguages": "Moje języki",
"addLanguage": "Dodaj język",
"selectLanguage": "Wybierz język, którego chcesz się uczyć",
Expand Down
1 change: 1 addition & 0 deletions messages/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Neerlandês",
"ro": "Romeno",
"ru": "Russo",
"tr": "Turco",
"myLanguages": "Meus idiomas",
"addLanguage": "Adicionar idioma",
"selectLanguage": "Selecione o idioma que deseja aprender",
Expand Down
1 change: 1 addition & 0 deletions messages/ro.json
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,7 @@
"nl": "Olandeză",
"ro": "Română",
"ru": "Rusă",
"tr": "Turcă",
"myLanguages": "Limbile mele",
"addLanguage": "Adaugă limbă",
"selectLanguage": "Alege limba pe care vrei să o înveți",
Expand Down
Loading
Loading