@@ -2,6 +2,8 @@ import { useState } from 'react';
22import { useQuery , gql } from '@apollo/client' ;
33import { PlusIcon , PencilIcon , ArrowDownTrayIcon , ClipboardIcon , CheckIcon } from '@heroicons/react/24/outline' ;
44import { useI18n , SUPPORTED_LANGUAGES , LANGUAGE_NAMES } from '../../providers/I18nProvider' ;
5+ import { useUIStore } from '../../stores/uiStore' ;
6+ import { useAuthStore } from '../../stores/authStore' ;
57import TranslationModal from './TranslationModal' ;
68
79const GET_TRANSLATION_KEYS = gql `
@@ -13,6 +15,7 @@ const GET_TRANSLATION_KEYS = gql`
1315 values {
1416 language
1517 valueText
18+ companyId
1619 }
1720 }
1821 }
@@ -21,6 +24,7 @@ const GET_TRANSLATION_KEYS = gql`
2124interface TranslationValue {
2225 language : string ;
2326 valueText : string ;
27+ companyId ?: string | null ;
2428}
2529
2630interface TranslationKey {
@@ -32,6 +36,8 @@ interface TranslationKey {
3236
3337export default function TranslationsPage ( ) {
3438 const { t, language, refreshTranslations } = useI18n ( ) ;
39+ const showTranslationKeys = useUIStore ( ( state ) => state . showTranslationKeys ) ;
40+ const currentCompanyId = useAuthStore ( ( state ) => state . currentCompanyId ) ;
3541 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
3642 const [ editingKey , setEditingKey ] = useState < TranslationKey | null > ( null ) ;
3743 const [ filterNamespace , setFilterNamespace ] = useState < string > ( '' ) ;
@@ -68,12 +74,27 @@ export default function TranslationsPage() {
6874 // Filter translations
6975 const filteredKeys = data ?. translationKeys ?. filter ( ( tk : TranslationKey ) => {
7076 const matchesNamespace = ! filterNamespace || tk . namespace === filterNamespace ;
77+ const fullKey = `${ tk . namespace } .${ tk . keyName } ` . toLowerCase ( ) ;
7178 const matchesSearch = ! searchTerm ||
79+ tk . namespace . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
7280 tk . keyName . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ||
81+ fullKey . includes ( searchTerm . toLowerCase ( ) ) ||
7382 tk . values . some ( v => v . valueText . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) ) ;
7483 return matchesNamespace && matchesSearch ;
7584 } ) || [ ] ;
7685
86+ const getEffectiveValue = ( tk : TranslationKey , lang : string ) : string | undefined => {
87+ if ( currentCompanyId ) {
88+ const companyValue = tk . values . find ( v => v . language === lang && v . companyId === currentCompanyId ) ;
89+ if ( companyValue ?. valueText ) {
90+ return companyValue . valueText ;
91+ }
92+ }
93+
94+ const defaultValue = tk . values . find ( v => v . language === lang && ( v . companyId === null || v . companyId === undefined ) ) ;
95+ return defaultValue ?. valueText ;
96+ } ;
97+
7798 return (
7899 < div className = "flex flex-col h-full" >
79100 { /* Header */ }
@@ -136,6 +157,15 @@ export default function TranslationsPage() {
136157 </ p >
137158 </ div >
138159
160+ { showTranslationKeys && (
161+ < div className = "mb-4 rounded-lg border border-amber-200 bg-amber-50 p-3 dark:border-amber-800 dark:bg-amber-900/20" >
162+ < p className = "text-sm text-amber-800 dark:text-amber-300" >
163+ < span className = "font-semibold" > Key display mode is active.</ span > { ' ' }
164+ The UI intentionally shows translation keys (like < code className = "rounded bg-amber-100 px-1.5 py-0.5 font-mono text-xs dark:bg-amber-900/50" > nav.templates</ code > ) instead of translated text.
165+ </ p >
166+ </ div >
167+ ) }
168+
139169 { /* Table */ }
140170 < div className = "bg-white dark:bg-gray-800 rounded-lg shadow overflow-hidden flex-1 min-h-0" >
141171 < div className = "overflow-x-auto h-full" >
@@ -185,18 +215,18 @@ export default function TranslationsPage() {
185215 < tr key = { tk . id } className = "hover:bg-gray-50 dark:hover:bg-gray-700/50" >
186216 < td className = "whitespace-nowrap px-6 py-4 font-mono text-sm" >
187217 < div className = "flex items-center gap-2" >
188- < span > { tk . keyName } </ span >
218+ < span > { fullKey } </ span >
189219 < CopyRefButton refKey = { fullKey } />
190220 </ div >
191221 </ td >
192222 < td className = "whitespace-nowrap px-6 py-4 text-gray-500 dark:text-gray-400" >
193223 { tk . namespace }
194224 </ td >
195225 { SUPPORTED_LANGUAGES . map ( ( lang ) => {
196- const value = tk . values . find ( v => v . language === lang ) ;
226+ const valueText = getEffectiveValue ( tk , lang ) ;
197227 return (
198228 < td key = { lang } className = "max-w-xs truncate px-6 py-4" >
199- { value ?. valueText || (
229+ { valueText || (
200230 < span className = "text-gray-400 italic" >
201231 { t ( 'translations.missing' ) }
202232 </ span >
@@ -225,6 +255,7 @@ export default function TranslationsPage() {
225255 { isModalOpen && (
226256 < TranslationModal
227257 translationKey = { editingKey }
258+ companyId = { currentCompanyId }
228259 onSaved = { handleModalSaved }
229260 onClose = { handleModalClose }
230261 />
0 commit comments