Skip to content

OGL-1395: i18n improvements#30

Merged
mravcak merged 7 commits into
mainfrom
OGL-1395-i18n-improvements
Jun 18, 2026
Merged

OGL-1395: i18n improvements#30
mravcak merged 7 commits into
mainfrom
OGL-1395-i18n-improvements

Conversation

@mravcak

@mravcak mravcak commented May 25, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

Release Notes

  • New Features

    • ETNO: Added language support with URL-based language switching (Slovak and English) with automatic header detection.
    • Archeo: Fully localized user interface with Slovak translations across all UI elements.
  • Bug Fixes

    • ETNO: Improved error handling on detail pages with proper error state recovery.

@notion-workspace

Copy link
Copy Markdown

Lokalizácia

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@mravcak, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 40 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: bb40dbdf-24ab-4d36-a53b-df248f9007d7

📥 Commits

Reviewing files that changed from the base of the PR and between 07ee827 and bc6fde3.

📒 Files selected for processing (1)
  • apps/etno/src/router/index.ts
📝 Walkthrough

Walkthrough

The PR implements URL-based language-prefixed routing in apps/etno (routes under /:lang(sk|en), a beforeEach guard synchronizing the i18n locale, per-locale backend translation JSON files fetched at build time, and an Axios Accept-Language interceptor), and separately adds vue-i18n to apps/archeo with a full Slovak translation dictionary and migrates all hardcoded strings across archeo components and views to $t(...) lookups.

Changes

etno: URL-Based i18n Routing & Backend Translations

Layer / File(s) Summary
Per-locale backend translation assets and i18n configuration
apps/etno/package.json, apps/etno/src/i18n/backend-defined/download.sh, apps/etno/src/i18n/backend-defined/en.json, apps/etno/src/i18n/backend-defined/sk.json, apps/etno/src/i18n/index.ts
Removes the single combined backend translations JSON; adds per-locale sk.json/en.json under backend-defined/; adds a download.sh that fetches them from the translations API using curl; updates the build script to run i18n:download sequentially before type-check; refactors i18n/index.ts to merge per-locale backend JSON into createI18n messages and export SUPPORTED_LANGS and isSupportedLang.
/:lang URL prefix, nested routes, and beforeEach locale sync
apps/etno/src/router/index.ts
Imports i18n helpers; restructures routes under a top-level /:lang(sk|en) segment with nested child routes; redirects / to the current locale; adds a beforeEach guard that reads to.params.lang and updates i18n.global.locale.value when isSupportedLang passes.
Language switch via router navigation, API Accept-Language header, and DetailView error handling
apps/etno/src/components/EtnoHeader.vue, apps/etno/src/api/index.ts, apps/etno/src/views/DetailView.vue
EtnoHeader replaces direct $i18n.locale mutation with a switchLang helper that calls router.push preserving route state; the Axios client gains a request interceptor setting Accept-Language from i18n.global.locale.value; DetailView wraps getDetail in try/catch and navigates to Error404 on failure.

archeo: vue-i18n Adoption

Layer / File(s) Summary
vue-i18n dependency, Slovak translation dictionary, instance configuration, and app registration
apps/archeo/package.json, apps/archeo/src/i18n/index.ts, apps/archeo/src/i18n/sk.json, apps/archeo/src/main.ts
Adds vue-i18n ^11.3.0; creates i18n/index.ts with createI18n for Slovak locale/fallback, legacy: false, globalInjection: true, and Slovak plural rules; introduces the full sk.json dictionary covering all UI sections; registers i18n in main.ts via app.use(i18n).
Component i18n migration
apps/archeo/src/components/ArcheoHeader.vue, apps/archeo/src/components/ArcheoMap/..., apps/archeo/src/components/ActivityLevel.vue, apps/archeo/src/components/ActivityList/..., apps/archeo/src/components/Detail/..., apps/archeo/src/components/Filter/FilterWidget.vue, apps/archeo/src/components/ModalIntro.vue
Replaces all hardcoded Slovak/Czech strings with $t(...) lookups across archeo components: header nav labels, map controls and tile-type options, map popover text, activity level labels, activity list count/sort options, pagination aria-labels, table column headers, boolean values, document/gallery/modal text, filter labels, and intro modal content.
View i18n migration
apps/archeo/src/views/DetailView.vue, apps/archeo/src/views/DetailGalleryView.vue, apps/archeo/src/views/InfoView.vue, apps/archeo/src/views/Error404View.vue
Migrates archeo views from hardcoded strings: DetailView rewrites all section titles, district/activity number formatting, and the tables computed structure; DetailGalleryView localizes the back button; InfoView localizes its header and body paragraphs; Error404View localizes its title and error text.

Sequence Diagram(s)

sequenceDiagram
  rect rgba(100, 149, 237, 0.5)
    Note over BuildScript,TranslationsAPI: Build-time translation fetch
    participant BuildScript
    participant download.sh
    participant TranslationsAPI
    BuildScript->>download.sh: run i18n:download
    download.sh->>TranslationsAPI: GET /api/etno/translations (Accept-Language: sk)
    TranslationsAPI-->>download.sh: sk.json
    download.sh->>TranslationsAPI: GET /api/etno/translations (Accept-Language: en)
    TranslationsAPI-->>download.sh: en.json
  end
  rect rgba(144, 238, 144, 0.5)
    Note over EtnoHeader,API: Runtime language switching and locale-aware API requests
    participant EtnoHeader
    participant Router
    participant BeforeEach
    participant I18n
    participant AxiosInterceptor
    participant API
    EtnoHeader->>Router: switchLang → router.push({lang})
    Router->>BeforeEach: beforeEach(to)
    BeforeEach->>I18n: i18n.global.locale.value = to.params.lang
    AxiosInterceptor->>I18n: read locale.value
    AxiosInterceptor->>API: request with Accept-Language: lang
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • metafori-studio/collection-toolbox-frontend#5: Introduced the etno prototype files including apps/etno/src/router/index.ts and apps/etno/src/api/index.ts, which this PR directly modifies to add language-prefixed routing and the Accept-Language interceptor.
  • metafori-studio/collection-toolbox-frontend#10: Established the initial apps/etno/src/i18n/index.ts i18n setup that this PR refactors to split into per-locale backend message files and export SUPPORTED_LANGS/isSupportedLang.
  • metafori-studio/collection-toolbox-frontend#23: Modified apps/etno/src/views/DetailView.vue initialization logic, the same component this PR changes to add try/catch error handling and Error404 navigation in onMounted.

Suggested reviewers

  • rastislav-chynoransky
  • igor-kamil

Poem

🐇 Hoppity-hop through routes that say /:lang,
Each URL now carries its tongue!
The bunny downloads sk and en with curl flair,
And headers whisper the locale through air.
Archeo and Etno both speak what they must —
No more hardcoded strings, in $t(...) we trust! 🌍

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'OGL-1395: i18n improvements' directly describes the main objective of the pull request and is related to the core changes throughout both apps/etno and apps/archeo focusing on internationalization enhancements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch OGL-1395-i18n-improvements

Warning

Review ran into problems

🔥 Problems

Stopped waiting for pipeline failures after 30000ms. One of your pipelines takes longer than our 30000ms fetch window to run, so review may not consider pipeline-failure results for inline comments if any failures occurred after the fetch window. Increase the timeout if you want to wait longer or run a @coderabbit review after the pipeline has finished.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mravcak

mravcak commented May 26, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/etno/src/i18n/backend-defined/download.sh`:
- Around line 1-11: The script download.sh lacks a shebang/strict mode and
doesn't fail on HTTP errors; update it to start with a shebang and enable strict
flags (e.g., set -euo pipefail), then make the two curl invocations use --fail
--show-error (and --location if redirects expected) and write to temporary files
before atomically moving to "$DIR/sk.json" and "$DIR/en.json" to avoid leaving
partial files; refer to download.sh, the DIR variable, and the two curl calls
that output "$DIR/sk.json" and "$DIR/en.json" when applying the changes.

In `@apps/etno/src/i18n/backend-defined/en.json`:
- Line 1: The enums.ItemType.photograph entry currently contains the raw token
"etno::enums.ItemType.photograph" (in backend-defined locales en.json and
sk.json) which may surface in the UI; update the enums.ItemType.photograph value
to a proper localized label (e.g., "photograph" or the Slovak equivalent) so the
key enums.ItemType.photograph resolves to a human-readable string rather than
the token.

In `@apps/etno/src/i18n/index.ts`:
- Around line 8-9: SUPPORTED_LANGS is currently inferred as string[]; change its
declaration to a literal tuple by appending "as const" to the array (const
SUPPORTED_LANGS = ['sk', 'en'] as const) and export a derived type (export type
SupportedLang = typeof SUPPORTED_LANGS[number]); then update the router
beforeEach guard to use SupportedLang for the lang variable (remove the manual
cast to 'sk' | 'en') so the type system knows the allowed values without
casting.

In `@apps/etno/src/router/index.ts`:
- Line 14: Replace the hardcoded language regex in the router with a derived
regex from SUPPORTED_LANGS: import SUPPORTED_LANGS from
apps/etno/src/i18n/index.ts, build a pipe-separated regex string (e.g.
SUPPORTED_LANGS.join('|')) and use it in both path definitions that currently
use '/:lang(sk|en)' and '/:lang(sk|en)/:pathMatch(.*)*' so they become
'/:lang(<langsRegex>)' and '/:lang(<langsRegex>)/:pathMatch(.*)*' respectively;
update the references in router/index.ts where the symbols '/:lang(sk|en)' and
'/:lang(sk|en)/:pathMatch(.*)*' appear to use the generated regex.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 722f7835-6c5c-4c6f-ad65-ec04b2f85f07

📥 Commits

Reviewing files that changed from the base of the PR and between 432182f and 4882826.

📒 Files selected for processing (9)
  • apps/etno/package.json
  • apps/etno/src/api/index.ts
  • apps/etno/src/components/AppHeader.vue
  • apps/etno/src/i18n/backend-defined-translations.json
  • apps/etno/src/i18n/backend-defined/download.sh
  • apps/etno/src/i18n/backend-defined/en.json
  • apps/etno/src/i18n/backend-defined/sk.json
  • apps/etno/src/i18n/index.ts
  • apps/etno/src/router/index.ts
💤 Files with no reviewable changes (1)
  • apps/etno/src/i18n/backend-defined-translations.json

Comment thread apps/etno/src/i18n/backend-defined/download.sh Outdated
@@ -0,0 +1 @@
{"enums":{"AccessRights":{"open-access":"open access","restricted-access":"restricted access","embargoed-access":"embargoed access","metadata-only-access":"metadata only access","paid-access":"paid access","closed-access":"closed access"},"AccrualMethod":{"deposit":"deposit","donation":"donation","exchange":"exchange","harvesting":"harvesting","legal-deposit":"legal deposit","loan":"loan","purchase":"purchase","subscription":"subscription","transfer":"transfer","work-made-for-hire":"work made for hire"},"CollectionMethod":{"archival-research":"archival research","field-research":"field research","survey":"survey"},"ExtentUnit":{"drawing":"drawing","duration":"duration","item":"item","page":"page","photograph":"photograph","research-slip":"research slip","volume":"volume"},"ItemType":{"audio-recording":"audio recording","bachelors-thesis":"bachelor's thesis","chronicle":"chronicle","copy":"copy","correspondence":"correspondence","dissertation-thesis":"dissertation thesis","drawing":"drawing","excerpt":"excerpt","floor-plan":"floor plan","illustration":"illustration","interview":"interview","map":"map","masters-thesis":"master's thesis","media-research":"media research","memory-book":"memory book","monograph":"monograph","musical-score":"musical score","newspaper-article":"newspaper article","personal-papers":"personal papers","photograph":"etno::enums.ItemType.photograph","photographic-negative":"photographic negative","photographic-slide":"photographic slide","physical-object":"physical object","questionnaire":"questionnaire","reproduction":"reproduction","research-paper":"research paper","research-report":"research report","song":"song","statistical-data":"statistical data","term-paper-seminar-paper":"term paper \/ seminar paper","transcription":"transcription","translation":"translation","video-recording":"video recording","web-page":"web page"},"Language":{"aar":"Afar","abk":"Abkhazian","ace":"Achinese","ach":"Acoli","ada":"Adangme","ady":"Adyghe; Adygei","afa":"Afro-Asiatic languages","afh":"Afrihili","afr":"Afrikaans","ain":"Ainu","aka":"Akan","akk":"Akkadian","sqi":"Albanian","ale":"Aleut","alg":"Algonquian languages","alt":"Southern Altai","amh":"Amharic","ang":"English, Old (ca.450-1100)","anp":"Angika","apa":"Apache languages","ara":"Arabic","arc":"Official Aramaic (700-300 BCE); Imperial Aramaic (700-300 BCE)","arg":"Aragonese","hye":"Armenian","arn":"Mapudungun; Mapuche","arp":"Arapaho","art":"Artificial languages","arw":"Arawak","asm":"Assamese","ast":"Asturian; Bable; Leonese; Asturleonese","ath":"Athapascan languages","aus":"Australian languages","ava":"Avaric","ave":"Avestan","awa":"Awadhi","aym":"Aymara","aze":"Azerbaijani","bad":"Banda languages","bai":"Bamileke languages","bak":"Bashkir","bal":"Baluchi","bam":"Bambara","ban":"Balinese","eus":"Basque","bas":"Basa","bat":"Baltic languages","bej":"Beja; Bedawiyet","bel":"Belarusian","bem":"Bemba","ben":"Bengali","ber":"Berber languages","bho":"Bhojpuri","bih":"Bihari languages","bik":"Bikol","bin":"Bini; Edo","bis":"Bislama","bla":"Siksika","bnt":"Bantu languages","bos":"Bosnian","bra":"Braj","bre":"Breton","btk":"Batak languages","bua":"Buriat","bug":"Buginese","bul":"Bulgarian","mya":"Burmese","byn":"Blin; Bilin","cad":"Caddo","cai":"Central American Indian languages","car":"Galibi Carib","cat":"Catalan; Valencian","cau":"Caucasian languages","ceb":"Cebuano","cel":"Celtic languages","cha":"Chamorro","chb":"Chibcha","che":"Chechen","chg":"Chagatai","zho":"Chinese","chk":"Chuukese","chm":"Mari","chn":"Chinook jargon","cho":"Choctaw","chp":"Chipewyan; Dene Suline","chr":"Cherokee","chu":"Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic","chv":"Chuvash","chy":"Cheyenne","cmc":"Chamic languages","cnr":"Montenegrin","cop":"Coptic","cor":"Cornish","cos":"Corsican","cpe":"Creoles and pidgins, English based","cpf":"Creoles and pidgins, French-based","cpp":"Creoles and pidgins, Portuguese-based","cre":"Cree","crh":"Crimean Tatar; Crimean Turkish","crp":"Creoles and pidgins","csb":"Kashubian","cus":"Cushitic languages","ces":"Czech","dak":"Dakota","dan":"Danish","dar":"Dargwa","day":"Land Dayak languages","del":"Delaware","den":"Slave (Athapascan)","dgr":"Tlicho; Dogrib","din":"Dinka","div":"Divehi; Dhivehi; Maldivian","doi":"Dogri","dra":"Dravidian languages","dsb":"Lower Sorbian","dua":"Duala","dum":"Dutch, Middle (ca.1050-1350)","nld":"Dutch; Flemish","dyu":"Dyula","dzo":"Dzongkha","efi":"Efik","egy":"Egyptian (Ancient)","eka":"Ekajuk","elx":"Elamite","eng":"English","enm":"English, Middle (1100-1500)","epo":"Esperanto","est":"Estonian","ewe":"Ewe","ewo":"Ewondo","fan":"Fang","fao":"Faroese","fat":"Fanti","fij":"Fijian","fil":"Filipino; Pilipino","fin":"Finnish","fiu":"Finno-Ugrian languages","fon":"Fon","fra":"French","frm":"French, Middle (ca.1400-1600)","fro":"French, Old (842-ca.1400)","frr":"Northern Frisian","frs":"Eastern Frisian","fry":"Western Frisian","ful":"Fulah","fur":"Friulian","gaa":"Ga","gay":"Gayo","gba":"Gbaya","gem":"Germanic languages","kat":"Georgian","deu":"German","gez":"Geez","gil":"Gilbertese","gla":"Gaelic; Scottish Gaelic","gle":"Irish","glg":"Galician","glv":"Manx","gmh":"German, Middle High (ca.1050-1500)","goh":"German, Old High (ca.750-1050)","gon":"Gondi","gor":"Gorontalo","got":"Gothic","grb":"Grebo","grc":"Greek, Ancient (to 1453)","ell":"Greek, Modern (1453-)","grn":"Guarani","gsw":"Swiss German; Alemannic; Alsatian","guj":"Gujarati","gwi":"Gwich'in","hai":"Haida","hat":"Haitian; Haitian Creole","hau":"Hausa","haw":"Hawaiian","heb":"Hebrew","her":"Herero","hil":"Hiligaynon","him":"Himachali languages; Western Pahari languages","hin":"Hindi","hit":"Hittite","hmn":"Hmong; Mong","hmo":"Hiri Motu","hrv":"Croatian","hsb":"Upper Sorbian","hun":"Hungarian","hup":"Hupa","iba":"Iban","ibo":"Igbo","isl":"Icelandic","ido":"Ido","iii":"Sichuan Yi; Nuosu","ijo":"Ijo languages","iku":"Inuktitut","ile":"Interlingue; Occidental","ilo":"Iloko","ina":"Interlingua (International Auxiliary Language Association)","inc":"Indic languages","ind":"Indonesian","ine":"Indo-European languages","inh":"Ingush","ipk":"Inupiaq","ira":"Iranian languages","iro":"Iroquoian languages","ita":"Italian","jav":"Javanese","jbo":"Lojban","jpn":"Japanese","jpr":"Judeo-Persian","jrb":"Judeo-Arabic","kaa":"Kara-Kalpak","kab":"Kabyle","kac":"Kachin; Jingpho","kal":"Kalaallisut; Greenlandic","kam":"Kamba","kan":"Kannada","kar":"Karen languages","kas":"Kashmiri","kau":"Kanuri","kaw":"Kawi","kaz":"Kazakh","kbd":"Kabardian","kha":"Khasi","khi":"Khoisan languages","khm":"Central Khmer","kho":"Khotanese; Sakan","kik":"Kikuyu; Gikuyu","kin":"Kinyarwanda","kir":"Kirghiz; Kyrgyz","kmb":"Kimbundu","kok":"Konkani","kom":"Komi","kon":"Kongo","kor":"Korean","kos":"Kosraean","kpe":"Kpelle","krc":"Karachay-Balkar","krl":"Karelian","kro":"Kru languages","kru":"Kurukh","kua":"Kuanyama; Kwanyama","kum":"Kumyk","kur":"Kurdish","kut":"Kutenai","lad":"Ladino","lah":"Lahnda","lam":"Lamba","lao":"Lao","lat":"Latin","lav":"Latvian","lez":"Lezghian","lim":"Limburgan; Limburger; Limburgish","lin":"Lingala","lit":"Lithuanian","lol":"Mongo","loz":"Lozi","ltz":"Luxembourgish; Letzeburgesch","lua":"Luba-Lulua","lub":"Luba-Katanga","lug":"Ganda","lui":"Luiseno","lun":"Lunda","luo":"Luo (Kenya and Tanzania)","lus":"Lushai","mkd":"Macedonian","mad":"Madurese","mag":"Magahi","mah":"Marshallese","mai":"Maithili","mak":"Makasar","mal":"Malayalam","man":"Mandingo","mri":"Maori","map":"Austronesian languages","mar":"Marathi","mas":"Masai","msa":"Malay","mdf":"Moksha","mdr":"Mandar","men":"Mende","mga":"Irish, Middle (900-1200)","mic":"Mi'kmaq; Micmac","min":"Minangkabau","mis":"Uncoded languages","mkh":"Mon-Khmer languages","mlg":"Malagasy","mlt":"Maltese","mnc":"Manchu","mni":"Manipuri","mno":"Manobo languages","moh":"Mohawk","mon":"Mongolian","mos":"Mossi","mul":"Multiple languages","mun":"Munda languages","mus":"Creek","mwl":"Mirandese","mwr":"Marwari","myn":"Mayan languages","myv":"Erzya","nah":"Nahuatl languages","nai":"North American Indian languages","nap":"Neapolitan","nau":"Nauru","nav":"Navajo; Navaho","nbl":"Ndebele, South; South Ndebele","nde":"Ndebele, North; North Ndebele","ndo":"Ndonga","nds":"Low German; Low Saxon; German, Low; Saxon, Low","nep":"Nepali","new":"Nepal Bhasa; Newari","nia":"Nias","nic":"Niger-Kordofanian languages","niu":"Niuean","nno":"Norwegian Nynorsk; Nynorsk, Norwegian","nob":"Bokm\u00e5l, Norwegian; Norwegian Bokm\u00e5l","nog":"Nogai","non":"Norse, Old","nor":"Norwegian","nqo":"N'Ko","nso":"Pedi; Sepedi; Northern Sotho","nub":"Nubian languages","nwc":"Classical Newari; Old Newari; Classical Nepal Bhasa","nya":"Chichewa; Chewa; Nyanja","nym":"Nyamwezi","nyn":"Nyankole","nyo":"Nyoro","nzi":"Nzima","oci":"Occitan (post 1500)","oji":"Ojibwa","ori":"Oriya","orm":"Oromo","osa":"Osage","oss":"Ossetian; Ossetic","ota":"Turkish, Ottoman (1500-1928)","oto":"Otomian languages","paa":"Papuan languages","pag":"Pangasinan","pal":"Pahlavi","pam":"Pampanga; Kapampangan","pan":"Panjabi; Punjabi","pap":"Papiamento","pau":"Palauan","peo":"Persian, Old (ca.600-400 B.C.)","fas":"Persian","phi":"Philippine languages","phn":"Phoenician","pli":"Pali","pol":"Polish","pon":"Pohnpeian","por":"Portuguese","pra":"Prakrit languages","pro":"Proven\u00e7al, Old (to 1500); Occitan, Old (to 1500)","pus":"Pushto; Pashto","qaa-qtz":"Reserved for local use","que":"Quechua","raj":"Rajasthani","rap":"Rapanui","rar":"Rarotongan; Cook Islands Maori","roa":"Romance languages","roh":"Romansh","rom":"Romany","ron":"Romanian; Moldavian; Moldovan","run":"Rundi","rup":"Aromanian; Arumanian; Macedo-Romanian","rus":"Russian","sad":"Sandawe","sag":"Sango","sah":"Yakut","sai":"South American Indian languages","sal":"Salishan languages","sam":"Samaritan Aramaic","san":"Sanskrit","sas":"Sasak","sat":"Santali","scn":"Sicilian","sco":"Scots","sel":"Selkup","sem":"Semitic languages","sga":"Irish, Old (to 900)","sgn":"Sign Languages","shn":"Shan","sid":"Sidamo","sin":"Sinhala; Sinhalese","sio":"Siouan languages","sit":"Sino-Tibetan languages","sla":"Slavic languages","slk":"Slovak","slv":"Slovenian","sma":"Southern Sami","sme":"Northern Sami","smi":"Sami languages","smj":"Lule Sami","smn":"Inari Sami","smo":"Samoan","sms":"Skolt Sami","sna":"Shona","snd":"Sindhi","snk":"Soninke","sog":"Sogdian","som":"Somali","son":"Songhai languages","sot":"Sotho, Southern","spa":"Spanish; Castilian","srd":"Sardinian","srn":"Sranan Tongo","srp":"Serbian","srr":"Serer","ssa":"Nilo-Saharan languages","ssw":"Swati","suk":"Sukuma","sun":"Sundanese","sus":"Susu","sux":"Sumerian","swa":"Swahili","swe":"Swedish","syc":"Classical Syriac","syr":"Syriac","tah":"Tahitian","tai":"Tai languages","tam":"Tamil","tat":"Tatar","tel":"Telugu","tem":"Timne","ter":"Tereno","tet":"Tetum","tgk":"Tajik","tgl":"Tagalog","tha":"Thai","bod":"Tibetan","tig":"Tigre","tir":"Tigrinya","tiv":"Tiv","tkl":"Tokelau","tlh":"Klingon; tlhIngan-Hol","tli":"Tlingit","tmh":"Tamashek","tog":"Tonga (Nyasa)","ton":"Tonga (Tonga Islands)","tpi":"Tok Pisin","tsi":"Tsimshian","tsn":"Tswana","tso":"Tsonga","tuk":"Turkmen","tum":"Tumbuka","tup":"Tupi languages","tur":"Turkish","tut":"Altaic languages","tvl":"Tuvalu","twi":"Twi","tyv":"Tuvinian","udm":"Udmurt","uga":"Ugaritic","uig":"Uighur; Uyghur","ukr":"Ukrainian","umb":"Umbundu","und":"Undetermined","urd":"Urdu","uzb":"Uzbek","vai":"Vai","ven":"Venda","vie":"Vietnamese","vol":"Volap\u00fck","vot":"Votic","wak":"Wakashan languages","wal":"Wolaitta; Wolaytta","war":"Waray","was":"Washo","cym":"Welsh","wen":"Sorbian languages","wln":"Walloon","wol":"Wolof","xal":"Kalmyk; Oirat","xho":"Xhosa","yao":"Yao","yap":"Yapese","yid":"Yiddish","yor":"Yoruba","ypk":"Yupik languages","zap":"Zapotec","zbl":"Blissymbols; Blissymbolics; Bliss","zen":"Zenaga","zgh":"Standard Moroccan Tamazight","zha":"Zhuang; Chuang","znd":"Zande languages","zul":"Zulu","zun":"Zuni","zxx":"No linguistic content; Not applicable","zza":"Zaza; Dimili; Dimli; Kirdki; Kirmanjki; Zazaki"},"License":{"cc-by":"CC BY","cc-by-nc":"CC BY-NC","cc-by-nc-nd":"CC BY-NC-ND","cc-by-nc-sa":"CC BY-NC-SA","cc-by-nd":"CC BY-ND","cc-by-sa":"CC BY-SA","cc0":"CC0"},"ProductionMethod":{"audio-recording":"audio recording","dot-matrix-printing":"dot matrix printing","drawing":"drawing","electronic-text":"electronic text","handwriting":"handwriting","inkjet-printing":"inkjet printing","laser-printing":"laser printing","painting":"painting","photocopy":"photocopy","photography":"photography","typewriting":"typewriting","video-recording":"video recording"}}} No newline at end of file

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify unresolved translation tokens in backend-defined locale payloads.
rg -n "etno::enums\\." apps/etno/src/i18n/backend-defined/en.json apps/etno/src/i18n/backend-defined/sk.json

Repository: metafori-studio/collection-toolbox-frontend

Length of output: 28153


Fix unresolved enum token ItemType.photograph in backend-defined locales

  • apps/etno/src/i18n/backend-defined/en.json (and apps/etno/src/i18n/backend-defined/sk.json) sets enums.ItemType.photograph to the raw token etno::enums.ItemType.photograph instead of a localized label, so the token can leak into UI.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/etno/src/i18n/backend-defined/en.json` at line 1, The
enums.ItemType.photograph entry currently contains the raw token
"etno::enums.ItemType.photograph" (in backend-defined locales en.json and
sk.json) which may surface in the UI; update the enums.ItemType.photograph value
to a proper localized label (e.g., "photograph" or the Slovak equivalent) so the
key enums.ItemType.photograph resolves to a human-readable string rather than
the token.

Comment thread apps/etno/src/i18n/index.ts Outdated
Comment thread apps/etno/src/router/index.ts Outdated
@mravcak mravcak force-pushed the OGL-1395-i18n-improvements branch from 4882826 to e665a47 Compare May 26, 2026 13:10
@mravcak mravcak force-pushed the OGL-1395-i18n-improvements branch from e665a47 to 07ee827 Compare June 17, 2026 08:50
@mravcak mravcak marked this pull request as ready for review June 17, 2026 08:54
@mravcak

mravcak commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/archeo/src/components/Detail/ModalAttachmentRequest.vue`:
- Around line 33-38: The BaseButton with the label attachmentRequest.close has
no `@click` event handler and the modal is hardcoded with :is-open="true", making
the close button non-functional. Add an `@click` handler to the BaseButton that
emits a close event or updates the parent state to toggle the modal's open
state, and ensure the modal's :is-open binding responds to this state change so
the modal actually closes when the button is clicked.

In `@apps/etno/src/router/index.ts`:
- Around line 45-52: The ForgotPassword and ResetPassword routes are using
absolute paths starting with a forward slash, which override the parent /:lang
route parameter and break locale-sync logic that depends on reading
to.params.lang. Change the path property for the ForgotPassword route from
/forgot-password to forgot-password (relative path) and the path property for
the ResetPassword route from /reset-password to reset-password (relative path),
so these child routes inherit the /:lang parameter from their parent route.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 50d92f7e-6b8d-4f52-9ead-6369f81dc942

📥 Commits

Reviewing files that changed from the base of the PR and between 4882826 and 07ee827.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (31)
  • apps/archeo/package.json
  • apps/archeo/src/components/ActivityLevel.vue
  • apps/archeo/src/components/ActivityList/ActivityList.vue
  • apps/archeo/src/components/ActivityList/ActivityListPagination.vue
  • apps/archeo/src/components/ActivityList/ActivityTable.vue
  • apps/archeo/src/components/ArcheoHeader.vue
  • apps/archeo/src/components/ArcheoMap/ArcheoMap.vue
  • apps/archeo/src/components/ArcheoMap/ArcheoMapPopover.vue
  • apps/archeo/src/components/Detail/DetailTable.vue
  • apps/archeo/src/components/Detail/DocumentCard.vue
  • apps/archeo/src/components/Detail/GalleryCard.vue
  • apps/archeo/src/components/Detail/ModalAttachmentRequest.vue
  • apps/archeo/src/components/Filter/FilterWidget.vue
  • apps/archeo/src/components/ModalIntro.vue
  • apps/archeo/src/i18n/index.ts
  • apps/archeo/src/i18n/sk.json
  • apps/archeo/src/main.ts
  • apps/archeo/src/views/DetailGalleryView.vue
  • apps/archeo/src/views/DetailView.vue
  • apps/archeo/src/views/Error404View.vue
  • apps/archeo/src/views/InfoView.vue
  • apps/etno/package.json
  • apps/etno/src/api/index.ts
  • apps/etno/src/components/EtnoHeader.vue
  • apps/etno/src/i18n/backend-defined-translations.json
  • apps/etno/src/i18n/backend-defined/download.sh
  • apps/etno/src/i18n/backend-defined/en.json
  • apps/etno/src/i18n/backend-defined/sk.json
  • apps/etno/src/i18n/index.ts
  • apps/etno/src/router/index.ts
  • apps/etno/src/views/DetailView.vue
💤 Files with no reviewable changes (1)
  • apps/etno/src/i18n/backend-defined-translations.json

Comment on lines 33 to 38
<BaseButton
variant="secondary"
block
>
Zavrieť
{{ $t('attachmentRequest.close') }}
</BaseButton>

@coderabbitai coderabbitai Bot Jun 17, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Close button has no behavior.

Line 33–38 renders a “close” action, but there is no @click handler (and the modal is hard-opened with :is-open="true"), so this CTA is non-functional.

Suggested fix
<script setup lang="ts">
 import {
   ModalWindow,
   BaseButton,
 } from '`@metafori/components`';

+const emit = defineEmits<{
+  close: [];
+}>();
+
 const sendEmail = () => { window.open('mailto:sekretariat@savba.sk'); };
</script>
       <BaseButton
         variant="secondary"
         block
+        `@click`="emit('close')"
       >
         {{ $t('attachmentRequest.close') }}
       </BaseButton>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/archeo/src/components/Detail/ModalAttachmentRequest.vue` around lines 33
- 38, The BaseButton with the label attachmentRequest.close has no `@click` event
handler and the modal is hardcoded with :is-open="true", making the close button
non-functional. Add an `@click` handler to the BaseButton that emits a close event
or updates the parent state to toggle the modal's open state, and ensure the
modal's :is-open binding responds to this state change so the modal actually
closes when the button is clicked.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood, @mravcak! Would you like me to open a follow-up GitHub issue to track the missing close-button handler in ModalAttachmentRequest.vue?


🧠 Learnings used
Learnt from: mravcak
Repo: metafori-studio/collection-toolbox-frontend PR: 36
File: apps/lidice-art/src/views/InfoView.vue:0-0
Timestamp: 2026-06-10T07:21:08.784Z
Learning: Tailwind CSS v4 changed the `important` modifier syntax: prefer the suffix form `utility!` (e.g., `text-3xl!`) instead of the legacy prefix form `!utility` (e.g., `!text-3xl`). While the old prefix still works for backward compatibility, code review should flag/encourage switching to the suffix form in Vue templates where Tailwind utilities are used.

Comment thread apps/etno/src/router/index.ts
@mravcak mravcak merged commit 639cc60 into main Jun 18, 2026
2 checks passed
@mravcak mravcak deleted the OGL-1395-i18n-improvements branch June 18, 2026 06:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants