slogan3

Help me bij het implementeren van een full-stack applicatie met meertalige ondersteuning

description

Het ondersteunen van meerdere talen stelt je in staat een breder publiek te bereiken, de tevredenheid van gebruikers te verbeteren en de toegankelijkheid voor gebruikers uit verschillende taalkundige achtergronden te vergroten.

prompt

try_prompt

Ik wil een full-stack applicatie bouwen die meerdere talen ondersteunt. Mijn frontend-technologie is {{frontend_technology}} en mijn backend-technologie is {{backend_technology}}. Geef een gedeta ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een uitgebreide gids voor het implementeren van internationalisatie (i18n) en lokalisatie (l10n) in jouw React- en Node.js-applicatie, inclusief beste praktijken voor vertalingen en gebruikersvoorkeuren. --- ## 1. Overzicht - **Internationalisatie (i18n):** Het proces van het voorbereiden van je applicatie op meerdere talen en regio’s zonder de code te wijzigen. - **Lokalisatie (l10n):** Het aanpassen van de inhoud aan specifieke regio’s, zoals vertalingen, datumnotaties, valuta, enz. --- ## 2. Structuur en architectuur ### Frontend (React) - Gebruik een i18n-bibliotheek zoals [react-i18next](https://react.i18next.com/). - Laad vertalingen dynamisch of statisch. - Detecteer of stel de taal in op basis van gebruikersvoorkeuren, browserinstellingen of URL. ### Backend (Node.js) - Gebruik bijvoorbeeld [i18next](https://www.i18next.com/) of [polyglot](https://github.com/airbnb/polyglot.js) voor server-side vertalingen. - Behandel regio- en taalgegevens, bijvoorbeeld via Accept-Language headers of gebruikersprofielen. --- ## 3. Implementatie in React ### Stap 1: Installatie ```bash npm install react-i18next i18next ``` ### Stap 2: Configuratie van i18n Maak een `i18n.js` bestand: ```javascript import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; // Vertalingen const resources = { en: { translation: { "welcome": "Welcome", "date": "{{date, date}}", // andere vertalingen } }, nl: { translation: { "welcome": "Welkom", "date": "{{date, date}}", // andere vertalingen } } // voeg meer talen toe }; i18n .use(initReactI18next) .init({ resources, lng: 'en', // standaardtaal fallbackLng: 'en', interpolation: { escapeValue: false, }, react: { useSuspense: false, }, }); export default i18n; ``` ### Stap 3: Gebruik in React componenten ```javascript import React from 'react'; import { useTranslation } from 'react-i18next'; function MijnComponent() { const { t, i18n } = useTranslation(); const changeLanguage = (lng) => { i18n.changeLanguage(lng); }; return ( <div> <h1>{t('welcome')}</h1> <button onClick={() => changeLanguage('nl')}>Nederlands</button> <button onClick={() => changeLanguage('en')}>English</button> </div> ); } ``` ### Stap 4: Taaldetectie en gebruikersvoorkeuren - Detecteer browsertaal via `navigator.language` en stel die in bij initiële lading. - Bewaar gebruikersvoorkeuren in cookies, localStorage of je database. - Bij elke sessie, haal de taalvoorkeur op en stel in via `i18n.changeLanguage()`. ```javascript import { useEffect } from 'react'; useEffect(() => { const savedLanguage = localStorage.getItem('language'); if (savedLanguage) { i18n.changeLanguage(savedLanguage); } else { const browserLanguage = navigator.language.startsWith('nl') ? 'nl' : 'en'; i18n.changeLanguage(browserLanguage); } }, []); ``` --- ## 4. Vertalingen beheren ### Bestanden - Gebruik gescheiden JSON-bestanden per taal voor onderhoudbaarheid, bijvoorbeeld `public/locales/en/translation.json`. - Voor grote projecten, overweeg een vertaalbeheerplatform zoals [Crowdin](https://crowdin.com/) of [Lokalise](https://lokalise.com/). ### Dynamische vertalingen - Laad vertalingen dynamisch via API of CDN om te ondersteunen dat vertalingen kunnen worden bijgewerkt zonder app-herstart. --- ## 5. Lokalisatie (l10n) praktijken ### Datumnotaties Gebruik bijvoorbeeld [date-fns](https://date-fns.org/) of [Intl.DateTimeFormat](https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat): ```javascript const formatter = new Intl.DateTimeFormat('nl-NL', { dateStyle: 'long' }); const formattedDate = formatter.format(new Date()); ``` ### Valuta ```javascript const formatter = new Intl.NumberFormat('nl-NL', { style: 'currency', currency: 'EUR' }); const prijs = formatter.format(1234.56); ``` ### Nummernotatie Gebruik dezelfde `Intl.NumberFormat` voor getallen, percentages, enz. --- ## 6. Best practices - **Scheiding van vertalingen:** Houd vertalingen gescheiden van bedrijfslogica. - **Fallbacks:** Stel fallback-talen in voor ontbrekende vertalingen. - **Context en pluralisatie:** Gebruik i18n-ondersteuning voor meervoud en context. - **Automatisering:** Automatiseer vertaalproces en updates. - **Gebruikersvoorkeuren:** Bewaar taalvoorkeuren persistent, bijvoorbeeld in userprofielen of cookies. - **Testen:** Test verschillende regio-instellingen en talen uitgebreid. --- ## 7. Samenvatting - Gebruik react-i18next voor React frontend. - Laad vertalingen gescheiden en dynamisch. - Detecteer en sla gebruikersvoorkeuren op. - Implementeer lokalisatie met `Intl` API en bibliotheken. - Beheer vertalingen centraal en update ze regelmatig. --- Mocht je verdere vragen hebben of hulp nodig bij specifieke code-implementaties, laat het gerust weten!
provider: deepseek
model: deepseek-chat
Zeker! Hier is een gedetailleerde gids voor het implementeren van internationalisatie (i18n) en lokalisatie (l10n) in jouw full-stack React/Node.js applicatie. ## 1. Frontend (React) Implementatie ### Installatie benodigde packages ```bash npm install i18next react-i18next i18next-http-backend i18next-browser-languagedetector ``` ### Basisconfiguratie ```javascript // src/i18n.js import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import Backend from 'i18next-http-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; i18n .use(Backend) .use(LanguageDetector) .use(initReactI18next) .init({ fallbackLng: 'nl', debug: process.env.NODE_ENV === 'development', interpolation: { escapeValue: false, }, backend: { loadPath: '/api/translations/{{lng}}/{{ns}}', }, detection: { order: ['localStorage', 'cookie', 'navigator'], caches: ['localStorage', 'cookie'], } }); export default i18n; ``` ### Gebruik in React componenten ```jsx // src/components/HomePage.js import React from 'react'; import { useTranslation } from 'react-i18next'; const HomePage = () => { const { t, i18n } = useTranslation(); const changeLanguage = (lng) => { i18n.changeLanguage(lng); }; return ( <div> <h1>{t('welcome_title')}</h1> <p>{t('welcome_message')}</p> <div> <button onClick={() => changeLanguage('nl')}>Nederlands</button> <button onClick={() => changeLanguage('en')}>English</button> <button onClick={() => changeLanguage('fr')}>Français</button> </div> </div> ); }; export default HomePage; ``` ### Geavanceerd gebruik met namespaces ```jsx // Gebruik met meerdere namespaces const { t } = useTranslation(['common', 'homepage']); // In je component t('common:save_button') t('homepage:hero_title') ``` ## 2. Backend (Node.js) Implementatie ### Vertalingen service ```javascript // services/translationService.js const translations = { nl: { common: { welcome_title: 'Welkom bij onze applicatie', save_button: 'Opslaan', cancel_button: 'Annuleren' }, homepage: { hero_title: 'Ontdek onze functies', description: 'Dit is een gelokaliseerde applicatie' } }, en: { common: { welcome_title: 'Welcome to our application', save_button: 'Save', cancel_button: 'Cancel' }, homepage: { hero_title: 'Discover our features', description: 'This is a localized application' } }, fr: { common: { welcome_title: 'Bienvenue dans notre application', save_button: 'Sauvegarder', cancel_button: 'Annuler' }, homepage: { hero_title: 'Découvrez nos fonctionnalités', description: 'Ceci est une application localisée' } } }; class TranslationService { getTranslation(language, namespace) { return translations[language]?.[namespace] || {}; } getAvailableLanguages() { return Object.keys(translations); } addTranslation(language, namespace, key, value) { if (!translations[language]) { translations[language] = {}; } if (!translations[language][namespace]) { translations[language][namespace] = {}; } translations[language][namespace][key] = value; } } module.exports = new TranslationService(); ``` ### API Routes ```javascript // routes/translations.js const express = require('express'); const router = express.Router(); const translationService = require('../services/translationService'); // GET /api/translations/:lng/:ns router.get('/:lng/:ns', (req, res) => { const { lng, ns } = req.params; const translation = translationService.getTranslation(lng, ns); if (Object.keys(translation).length === 0) { return res.status(404).json({ error: 'Translation not found' }); } res.json(translation); }); // GET /api/languages router.get('/languages/available', (req, res) => { const languages = translationService.getAvailableLanguages(); res.json(languages); }); module.exports = router; ``` ### Gebruikersvoorkeuren middleware ```javascript // middleware/languageMiddleware.js const getUserLanguage = (req) => { // Prioriteit: 1. Query parameter, 2. Cookie, 3. Accept-Language header, 4. Standaard return ( req.query.lang || req.cookies?.preferredLanguage || req.acceptsLanguages(['nl', 'en', 'fr']) || 'nl' ); }; const languageMiddleware = (req, res, next) => { const userLanguage = getUserLanguage(req); req.language = userLanguage; next(); }; module.exports = languageMiddleware; ``` ## 3. Database Structuur (Optioneel) ### Gebruikersvoorkeuren ```sql CREATE TABLE user_preferences ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), preferred_language VARCHAR(10) DEFAULT 'nl', timezone VARCHAR(50) DEFAULT 'Europe/Amsterdam', date_format VARCHAR(20) DEFAULT 'DD-MM-YYYY', created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); ``` ### Vertalingen database ```sql CREATE TABLE translations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), namespace VARCHAR(100) NOT NULL, language_code VARCHAR(10) NOT NULL, translation_key VARCHAR(200) NOT NULL, translation_value TEXT NOT NULL, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), UNIQUE(namespace, language_code, translation_key) ); ``` ## 4. Best Practices en Geavanceerde Features ### A. Vertalingen beheer ```javascript // scripts/extractTranslations.js const fs = require('fs'); const path = require('path'); // Automatisch extracten van vertaalsleutels uit code function extractKeysFromFiles(directory) { // Implementeer logica om sleutels te extraheren // Gebruik regex of AST parsing } ``` ### B. Plurale vormen ```javascript // In je vertalingen const translations = { en: { items_count: '{{count}} item', items_count_plural: '{{count}} items' }, nl: { items_count: '{{count}} item', items_count_plural: '{{count}} items' } }; // Gebruik in component t('items_count', { count: 5 }) // "5 items" ``` ### C. Datum/tijd lokalisatie ```javascript // services/dateService.js const { format } = require('date-fns'); const { nl, enUS, fr } = require('date-fns/locale'); const locales = { nl, en: enUS, fr }; const formatLocalizedDate = (date, formatString, language) => { return format(date, formatString, { locale: locales[language] }); }; module.exports = { formatLocalizedDate }; ``` ### D. Valuta en getallen ```javascript const formatLocalizedCurrency = (amount, currency, language) => { return new Intl.NumberFormat(language, { style: 'currency', currency: currency }).format(amount); }; ``` ## 5. Development Workflow ### A. Vertaalworkflow 1. **Extractie**: Gebruik tools zoals `i18next-scanner` om sleutels automatisch te extraheren 2. **Vertaling**: Exporteer naar .json of gebruik een vertaalplatform 3. **Review**: Laat native speakers vertalingen controleren 4. **Implementatie**: Voeg vertalingen toe aan je applicatie ### B. Quality Assurance ```javascript // tests/translation.test.js describe('Translations', () => { test('alle talen hebben dezelfde sleutels', () => { const languages = ['nl', 'en', 'fr']; const namespaces = ['common', 'homepage']; namespaces.forEach(namespace => { const baseKeys = Object.keys(translations.nl[namespace]); languages.forEach(language => { const languageKeys = Object.keys(translations[language][namespace]); expect(languageKeys).toEqual(baseKeys); }); }); }); }); ``` ## 6. Performance Optimalisaties ### A. Code splitting per taal ```javascript // Dynamisch importeren van vertalingen const loadTranslations = async (language) => { const translation = await import(`../locales/${language}/common.json`); i18n.addResourceBundle(language, 'common', translation); }; ``` ### B. Caching strategieën ```javascript // Service Worker voor offline vertalingen // of // Redis cache voor backend vertalingen ``` ## 7. Deployment Considerations ### Environment variabelen ```env DEFAULT_LANGUAGE=nl SUPPORTED_LANGUAGES=nl,en,fr FALLBACK_LANGUAGE=nl ``` ### Build process ```json // package.json scripts { "scripts": { "build:i18n": "i18next-scanner --config i18next-scanner.config.js", "extract:translations": "node scripts/extractTranslations.js" } } ``` Deze implementatie biedt een schaalbare, onderhoudbare aanpak voor internationalisatie in je full-stack applicatie. Begin met de basisimplementatie en breid uit met geavanceerde features naarmate je applicatie groeit.