Skip to content

Commit 90e7313

Browse files
committed
fix(i18n): add missing translations for app detail page.
Fixes #81 and #88. Add missing strings and fallbacks.
1 parent e7a4888 commit 90e7313

4 files changed

Lines changed: 112 additions & 17 deletions

File tree

components/AppStore/AppDetails.jsx

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ const AppDetails = () => {
7676

7777
const getGradeDescription = (grade) => {
7878
const gradeKey = grade?.toLowerCase();
79-
return t.appStore.details.grades[gradeKey] || "";
79+
return t.appStore?.details?.grades?.[gradeKey] || '';
8080
}
8181

8282
if (loading) {
8383
return (
8484
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-black">
8585
<div className="text-center">
8686
<div className="inline-block w-12 h-12 border-4 border-zinc-200 border-t-blue-600 rounded-full animate-spin mb-4"></div>
87-
<p className="text-zinc-500">{t.appStore.details.loading}</p>
87+
<p className="text-zinc-500">{t.appStore?.details?.loading || 'Loading app details...'}</p>
8888
</div>
8989
</div>
9090
);
@@ -94,8 +94,8 @@ const AppDetails = () => {
9494
return (
9595
<div className="min-h-screen flex items-center justify-center bg-zinc-50 dark:bg-black">
9696
<div className="text-center">
97-
<h1 className="text-2xl font-bold mb-4 text-zinc-900 dark:text-white">{t.appStore.details.notFound}</h1>
98-
<Link to="/appstore" className="text-blue-600 hover:underline">{t.appStore.details.back}</Link>
97+
<h1 className="text-2xl font-bold mb-4 text-zinc-900 dark:text-white">{t.appStore?.details?.notFound || 'App not found'}</h1>
98+
<Link to="/appstore" className="text-blue-600 hover:underline">{t.appStore?.details?.back || 'Back to App Store'}</Link>
9999
</div>
100100
</div>
101101
);
@@ -106,7 +106,7 @@ const AppDetails = () => {
106106
<section className="pt-32 pb-12 bg-white dark:bg-zinc-900/20 border-b border-zinc-200 dark:border-white/5">
107107
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
108108
<Link to="/appstore" className="inline-flex items-center text-zinc-500 hover:text-zinc-900 dark:hover:text-white mb-8 transition-colors">
109-
<ArrowLeft className="w-4 h-4 mr-2" /> {t.appStore.details.back}
109+
<ArrowLeft className="w-4 h-4 mr-2" /> {t.appStore?.details?.back || 'Back to App Store'}
110110
</Link>
111111

112112
<div className="flex flex-col md:flex-row gap-8 items-start">
@@ -138,15 +138,15 @@ const AppDetails = () => {
138138
className="inline-flex items-center px-6 py-3 rounded-full bg-blue-600 hover:bg-blue-700 text-white font-medium transition-colors"
139139
>
140140
<Download className="w-5 h-5 mr-2" />
141-
{t.appStore.details.install}
141+
{t.appStore?.details?.install || 'Install'}
142142
</Link>
143143
{reviewContent && (
144144
<button
145145
onClick={() => setShowReview(true)}
146146
className="inline-flex items-center px-6 py-3 rounded-full bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 text-zinc-900 dark:text-white font-medium transition-colors"
147147
>
148148
<Star className="w-5 h-5 mr-2" />
149-
{t.appStore.details.readReview}
149+
{t.appStore?.details?.readReview || 'Read review'}
150150
</button>
151151
)}
152152
</div>
@@ -168,7 +168,7 @@ const AppDetails = () => {
168168
<section>
169169
<h2 className="text-2xl font-bold text-zinc-900 dark:text-white mb-4 flex items-center gap-2">
170170
<Shield className="w-6 h-6 text-blue-600" />
171-
{t.appStore.details.aboutGrade.replace('{grade}', entry.Grade)}
171+
{(t.appStore?.details?.aboutGrade || 'About this {grade} app').replace('{grade}', entry.Grade)}
172172
</h2>
173173
<p className="text-zinc-600 dark:text-zinc-400 text-lg leading-relaxed">
174174
{getGradeDescription(entry.Grade)}
@@ -179,17 +179,17 @@ const AppDetails = () => {
179179
<section>
180180
<h2 className="text-2xl font-bold text-zinc-900 dark:text-white mb-6 flex items-center gap-2">
181181
<Package className="w-6 h-6 text-purple-600" />
182-
{t.appStore.details.dependencies.title}
182+
{t.appStore?.details?.dependencies?.title || 'Dependencies'}
183183
</h2>
184184
<p className="text-zinc-600 dark:text-zinc-400 mb-6">
185-
{t.appStore.details.dependencies.description}
185+
{t.appStore?.details?.dependencies?.description || 'These dependencies are required for the installer.'}
186186
</p>
187187
<div className="grid md:grid-cols-2 gap-4">
188188
{details.Dependencies.map(dep => (
189189
<div key={dep} className="bg-white dark:bg-zinc-900 p-6 rounded-xl border border-zinc-200 dark:border-zinc-800">
190190
<h3 className="font-bold text-zinc-900 dark:text-white mb-2">{dep}</h3>
191191
<p className="text-sm text-zinc-600 dark:text-zinc-400">
192-
{dependenciesData[dep]?.Description || t.appStore.details.dependencies.noDescription}
192+
{dependenciesData[dep]?.Description || t.appStore?.details?.dependencies?.noDescription || 'No description available.'}
193193
</p>
194194
</div>
195195
))}
@@ -201,24 +201,32 @@ const AppDetails = () => {
201201
<section>
202202
<h2 className="text-2xl font-bold text-zinc-900 dark:text-white mb-6 flex items-center gap-2">
203203
<Settings className="w-6 h-6 text-zinc-500" />
204-
{t.appStore.details.configuration.title}
204+
{t.appStore?.details?.configuration?.title || 'Configuration'}
205205
</h2>
206206
<p className="text-zinc-600 dark:text-zinc-400 mb-6">
207-
{t.appStore.details.configuration.description}
207+
{t.appStore?.details?.configuration?.description || 'The following configuration will be applied to your bottle:'}
208208
</p>
209209
<div className="bg-white dark:bg-zinc-900 p-6 rounded-xl border border-zinc-200 dark:border-zinc-800">
210210
<ul className="space-y-2">
211211
{Object.entries(details.Parameters).map(([param, value]) => (
212212
<li key={param} className="flex items-center gap-2 text-zinc-700 dark:text-zinc-300 font-mono text-sm">
213213
<div className={`w-2 h-2 rounded-full ${value ? 'bg-green-500' : 'bg-red-500'}`}></div>
214-
{param}: <span className={value ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}>{value ? t.appStore.details.configuration.enabled : t.appStore.details.configuration.disabled}</span>
214+
{param}: <span className={value ? 'text-green-600 dark:text-green-400' : 'text-red-600 dark:text-red-400'}>{value ? (t.appStore?.details?.configuration?.enabled || 'enabled') : (t.appStore?.details?.configuration?.disabled || 'disabled')}</span>
215215
</li>
216216
))}
217217
</ul>
218218
</div>
219219
</section>
220220
)}
221221

222+
<section className="py-6 bg-white dark:bg-zinc-900/20 rounded-2xl border border-zinc-200 dark:border-zinc-800">
223+
<div className="px-6">
224+
<p className="text-xs text-zinc-500 dark:text-zinc-400 leading-relaxed">
225+
{t.appStore?.details?.disclaimer || 'Bottles does not re-distribute or host the files but only downloads them from the vendor\'s official sources. These files are checked by our maintainers and do not contain viruses. However, they may be subject to copyright or licenses of different types, including proprietary ones.'}
226+
</p>
227+
</div>
228+
</section>
229+
222230
<section className="pt-8 border-t border-zinc-200 dark:border-zinc-800">
223231
<div className="flex flex-col sm:flex-row gap-4 justify-center">
224232
<a
@@ -227,15 +235,15 @@ const AppDetails = () => {
227235
rel="noopener noreferrer"
228236
className="flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 text-zinc-900 dark:text-white transition-colors"
229237
>
230-
{t.appStore.details.wineDb} <ExternalLink className="w-4 h-4" />
238+
{t.appStore?.details?.wineDb || 'More info on WineDB'} <ExternalLink className="w-4 h-4" />
231239
</a>
232240
<a
233241
href={`https://www.protondb.com/search?q=${entry.Name}`}
234242
target="_blank"
235243
rel="noopener noreferrer"
236244
className="flex items-center justify-center gap-2 px-6 py-3 rounded-xl bg-zinc-100 dark:bg-zinc-800 hover:bg-zinc-200 dark:hover:bg-zinc-700 text-zinc-900 dark:text-white transition-colors"
237245
>
238-
{t.appStore.details.protonDb} <ExternalLink className="w-4 h-4" />
246+
{t.appStore?.details?.protonDb || 'More info on ProtonDB'} <ExternalLink className="w-4 h-4" />
239247
</a>
240248
</div>
241249
</section>
@@ -245,7 +253,7 @@ const AppDetails = () => {
245253
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm animate-in fade-in duration-200">
246254
<div className="bg-white dark:bg-zinc-900 w-full max-w-3xl max-h-[80vh] rounded-2xl shadow-2xl flex flex-col">
247255
<div className="p-6 border-b border-zinc-200 dark:border-zinc-800 flex justify-between items-center">
248-
<h2 className="text-2xl font-bold text-zinc-900 dark:text-white">{t.appStore.details.review} {entry.Name}</h2>
256+
<h2 className="text-2xl font-bold text-zinc-900 dark:text-white">{t.appStore?.details?.review || 'Review for'} {entry.Name}</h2>
249257
<button onClick={() => setShowReview(false)} className="text-zinc-500 hover:text-zinc-900 dark:hover:text-white">
250258
<X className="w-6 h-6" />
251259
</button>

i18n/translations/en.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ export const en = {
2525
card: {
2626
details: 'Details',
2727
install: 'Install'
28+
},
29+
details: {
30+
loading: 'Loading app details...',
31+
notFound: 'App not found',
32+
back: 'Back to App Store',
33+
aboutGrade: 'About this {grade} app',
34+
grades: {
35+
bronze: 'This application works but not in the best way. The installer has configured your bottle to give you the best possible experience but you have to expect glitches, inaccessible features (e.g. multiplayer if it\'s a game) and other problems. In the future, this installer may receive updates to improve the result.',
36+
silver: 'This application works fine. There are some glitches, but they do not affect the application\'s functionality. All features are accessible and work as expected.',
37+
gold: 'This application works in the best way. There may be rare glitches but they do not affect the application\'s functionality. All features are accessible and work as expected.',
38+
platinum: 'This application works in the best way. There are no glitches. All features are accessible and work as expected, and the overall experience is smooth.',
39+
},
40+
dependencies: {
41+
title: 'Dependencies',
42+
description: 'The following dependencies will be automatically installed with this app:',
43+
noDescription: 'No description available.',
44+
},
45+
configuration: {
46+
title: 'Configuration',
47+
description: 'The following configuration will be applied to your bottle:',
48+
enabled: 'enabled',
49+
disabled: 'disabled',
50+
},
51+
install: 'How to Install',
52+
readReview: 'Read review',
53+
review: 'Review for',
54+
disclaimer: 'Bottles does not re-distribute or host the files but only downloads them from the vendor\'s official sources. These files are checked by our maintainers and do not contain viruses. However, they may be subject to copyright or licenses of different types, including proprietary ones.',
55+
wineDb: 'More info on WineDB',
56+
protonDb: 'More info on ProtonDB',
2857
}
2958
},
3059
hero: {

i18n/translations/es.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ export const es = {
2525
card: {
2626
details: 'Detalles',
2727
install: 'Instalar'
28+
},
29+
details: {
30+
loading: 'Cargando detalles de la aplicación...',
31+
notFound: 'Aplicación no encontrada',
32+
back: 'Volver a la Tienda de Aplicaciones',
33+
aboutGrade: 'Acerca de esta aplicación {grade}',
34+
grades: {
35+
bronze: 'Esta aplicación funciona, pero no de la mejor manera. El instalador ha configurado tu botella para ofrecerte la mejor experiencia posible, pero debes esperar fallos, funciones inaccesibles (por ejemplo, el multijugador si es un juego) y otros problemas. En el futuro, este instalador puede recibir actualizaciones para mejorar el resultado.',
36+
silver: 'Esta aplicación funciona bien. Hay algunos fallos, pero no afectan la funcionalidad de la aplicación. Todas las funciones están accesibles y funcionan como se espera.',
37+
gold: 'Esta aplicación funciona de la mejor manera. Puede haber fallos raros, pero no afectan la funcionalidad de la aplicación. Todas las funciones están accesibles y funcionan como se espera.',
38+
platinum: 'Esta aplicación funciona de la mejor manera. No hay fallos. Todas las funciones están accesibles y funcionan como se espera, y la experiencia general es fluida.',
39+
},
40+
dependencies: {
41+
title: 'Dependencias',
42+
description: 'Las siguientes dependencias se instalarán automáticamente con esta aplicación:',
43+
noDescription: 'No hay descripción disponible.',
44+
},
45+
configuration: {
46+
title: 'Configuración',
47+
description: 'La siguiente configuración se aplicará a tu botella:',
48+
enabled: 'habilitado',
49+
disabled: 'deshabilitado',
50+
},
51+
install: 'Cómo instalar',
52+
readReview: 'Leer reseña',
53+
review: 'Reseña de',
54+
disclaimer: 'Bottles no redistribuye ni aloja los archivos, solo los descarga desde las fuentes oficiales del proveedor. Estos archivos son revisados por nuestros mantenedores y no contienen virus. Sin embargo, pueden estar sujetos a derechos de autor o licencias de distintos tipos, incluidas licencias propietarias.',
55+
wineDb: 'Más información en WineDB',
56+
protonDb: 'Más información en ProtonDB',
2857
}
2958
},
3059
hero: {

i18n/translations/it.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,35 @@ export const it = {
2525
card: {
2626
details: 'Dettagli',
2727
install: 'Installa'
28+
},
29+
details: {
30+
loading: 'Caricamento dettagli app...',
31+
notFound: 'App non trovata',
32+
back: 'Torna all\'App Store',
33+
aboutGrade: 'Informazioni su questa app {grade}',
34+
grades: {
35+
bronze: 'Questa applicazione funziona, ma non nel modo migliore. L\'installer ha configurato la tua bottle per offrirti la migliore esperienza possibile, ma devi aspettarti glitch, funzionalita non accessibili (ad esempio il multiplayer se e un gioco) e altri problemi. In futuro, questo installer potrebbe ricevere aggiornamenti per migliorare il risultato.',
36+
silver: 'Questa applicazione funziona bene. Ci sono alcuni glitch, ma non influenzano la funzionalita dell\'applicazione. Tutte le funzionalita sono accessibili e funzionano come previsto.',
37+
gold: 'Questa applicazione funziona nel modo migliore. Potrebbero esserci rari glitch, ma non influenzano la funzionalita dell\'applicazione. Tutte le funzionalita sono accessibili e funzionano come previsto.',
38+
platinum: 'Questa applicazione funziona nel modo migliore. Non ci sono glitch. Tutte le funzionalita sono accessibili e funzionano come previsto, e l\'esperienza complessiva e fluida.',
39+
},
40+
dependencies: {
41+
title: 'Dipendenze',
42+
description: 'Le seguenti dipendenze verranno installate automaticamente con questa applicazione:',
43+
noDescription: 'Nessuna descrizione disponibile.',
44+
},
45+
configuration: {
46+
title: 'Configurazione',
47+
description: 'La seguente configurazione verra applicata alla tua bottle:',
48+
enabled: 'abilitato',
49+
disabled: 'disabilitato',
50+
},
51+
install: 'Come installare',
52+
readReview: 'Leggi la recensione',
53+
review: 'Recensione di',
54+
disclaimer: 'Bottles non ridistribuisce ne ospita i file, ma li scarica solo dalle fonti ufficiali del fornitore. Questi file sono controllati dai nostri maintainer e non contengono virus. Tuttavia, possono essere soggetti a copyright o licenze di vario tipo, incluse quelle proprietarie.',
55+
wineDb: 'Maggiori info su WineDB',
56+
protonDb: 'Maggiori info su ProtonDB',
2857
}
2958
},
3059
hero: {

0 commit comments

Comments
 (0)