å ç¢ã§ä¿å®æ§ã®é«ãå€èšèªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã®ãåå®å šãªåœéåïŒi18nïŒã®å©ç¹ãšå®è£ æŠç¥ãæ¢ããŸããåãæŽ»çšããŠäžè¬çãªi18nã®ãšã©ãŒãé²ããéçºè ã®çç£æ§ãåäžãããæ¹æ³ãåŠã³ãŸãã
åå®å šãªåœéåïŒi18nã®åå®è£ ã«é¢ããå æ¬çã¬ã€ã
仿¥ã®ã°ããŒãã«åãããäžçã§ã¯ããœãããŠã§ã¢ã¢ããªã±ãŒã·ã§ã³ã¯ãŸããŸãè€æ°ã®èšèªãå°åããµããŒãããããšãæ±ããããŠããŸããåœéåïŒi18nïŒã¯ãç°ãªãèšèªãæåçãªæ £ç¿ã«å®¹æã«é©å¿ã§ããã¢ããªã±ãŒã·ã§ã³ãèšèšã»éçºããããã»ã¹ã§ããããããi18nã¯è€éã§ãšã©ãŒãçºçãããããç¹ã«å€æ°ã®ç¿»èš³ãåçã³ã³ãã³ããæ±ãå Žåã«ã¯ãã®åŸåã匷ãŸããŸãã
ãã®ã¬ã€ãã§ã¯ãåå®å šãªåœéåã®æŠå¿µãæãäžããéçåä»ããæŽ»çšããŠi18nå®è£ ã®ä¿¡é Œæ§ãšä¿å®æ§ãåäžãããæ¹æ³ãæ¢ããŸããåå®å šã®å©ç¹ãããŸããŸãªå®è£ æŠç¥ããããŠäººæ°ã®i18nã©ã€ãã©ãªããã¬ãŒã ã¯ãŒã¯ã䜿çšããå®è·µçãªäŸã«ã€ããŠè§£èª¬ããŸãã
ãªãåå®å šãªåœéåãå¿ èŠãªã®ãïŒ
åŸæ¥ã®i18nã¢ãããŒãã¯ã翻蚳ãååŸããããã«æååããŒã¹ã®ããŒã«äŸåããããšããããããŸãããã®ã¢ãããŒãã¯ã·ã³ãã«ã§ãããããã€ãã®æ¬ ç¹ããããŸãã
- ã¿ã€ããšç¿»èš³ã®æ¬ èœïŒ 翻蚳ããŒã®åçŽãªã¿ã€ãããã©ã³ã¿ã€ã ãšã©ãŒãããã©ã«ãèšèªãžã®ãã©ãŒã«ããã¯ãåŒãèµ·ããå¯èœæ§ããããŸããåãã§ãã¯ããªããã°ããããã®ãšã©ãŒãéçºäžã«æ€åºããããšã¯å°é£ã§ãã
- ãªãã¡ã¯ã¿ãªã³ã°ã®èª²é¡ïŒ 翻蚳ããŒã®åå倿Žãåé€ã«ã¯ãã³ãŒãããŒã¹å šäœã§å šãŠã®åç §ãæåã§æŽæ°ããå¿ èŠããããŸãããã®ããã»ã¹ã¯é¢åã§ãšã©ãŒãçºçããããã§ãã
- ã³ãŒãè£å®ã®æ¬ åŠïŒ æååããŒã¹ã®ããŒã¯IDEã«åæ å ±ãæäŸããªããããå©çšå¯èœãªç¿»èš³ãçºèŠããããéçºäžã«ãšã©ãŒãææãããããããšãå°é£ã«ãªããŸãã
- ã©ã³ã¿ã€ã ãšã©ãŒïŒ 翻蚳ã«ããããã©ã¡ãŒã¿ã®æ¬ èœãäžæ£ãªãã©ãŒãããã¯ãç¹ã«åçã«çæãããã³ã³ãã³ãã«ãããŠãã©ã³ã¿ã€ã ã¯ã©ãã·ã¥ãåŒãèµ·ããå¯èœæ§ããããŸãã
åå®å šãªi18nã¯ãéçåä»ãã®åãæŽ»çšããŠã³ã³ãã€ã«æãã§ãã¯ãæäŸããå šäœçãªéçºè äœéšãåäžãããããšã§ããããã®åé¡ã«å¯ŸåŠããŸãã
i18nã«ãããåå®å šã®å©ç¹
- æ©æã®ãšã©ãŒæ€åºïŒ åãã§ãã¯ã«ãããã³ã³ãã€ã«æã«ã¿ã€ããç¿»èš³ã®æ¬ èœãææããã©ã³ã¿ã€ã ãšã©ãŒãé²ãããšãã§ããŸãã
- ãªãã¡ã¯ã¿ãªã³ã°ã®æ¹åïŒ åã·ã¹ãã ã¯ã翻蚳ããŒãåå倿ŽãŸãã¯åé€ãããéã«ãå šãŠã®åç §ãèªåçã«æ€åºã»æŽæ°ã§ããããããªãã¡ã¯ã¿ãªã³ã°ãç°¡çŽ åãããŸãã
- ã³ãŒãè£å®ã®åŒ·åïŒ åæ å ±ã«ãããIDEã翻蚳ããŒã®ã³ãŒãè£å®ãæäŸã§ããããã«ãªããå©çšå¯èœãªç¿»èš³ã容æã«çºèŠã§ããŸãã
- 翻蚳ãã©ã¡ãŒã¿ã®ã³ã³ãã€ã«ææ€èšŒïŒ åã·ã¹ãã ã¯ãç¿»èš³ã«æ£ãããã©ã¡ãŒã¿ãæž¡ãããããšãä¿èšŒãããã©ã¡ãŒã¿ã®æ¬ èœãäžæ£ãªãã©ãŒãããã«ããã©ã³ã¿ã€ã ãšã©ãŒãé²ããŸãã
- ã³ãŒããžã®ä¿¡é Œæ§ã®åäžïŒ åå®å šã¯ãi18nå®è£ ã®æ£ç¢ºæ§ãšä¿¡é Œæ§ã«å¯Ÿãããã倧ããªèªä¿¡ãæäŸããŸãã
åå®å šãªi18nã®å®è£ æŠç¥
䜿çšããŠããããã°ã©ãã³ã°èšèªãi18nã©ã€ãã©ãªã«å¿ããŠãåå®å šãªi18nãå®è£ ããããã«ããã€ãã®æŠç¥ããããŸãã以äžã«äžè¬çãªã¢ãããŒããããã€ã玹ä»ããŸãã
1. TypeScriptãšå°çši18nã©ã€ãã©ãªã®äœ¿çš
JavaScriptã®ã¹ãŒããŒã»ããã§ããTypeScriptã¯ãi18nã«å¹æçã«äœ¿çšã§ãã匷åãªåä»ãæ©èœãæäŸããŸãã`react-i18next`ã`next-i18next`ã®ãããªã©ã€ãã©ãªã¯ãããããReactãNext.jsã§äžè¬çã«äœ¿çšãããŸãããããã®ã©ã€ãã©ãªãTypeScriptãšçµã¿åãããããšã§ã翻蚳ããŒãšå€ã®åãå®çŸ©ããã³ã³ãã€ã«æãã§ãã¯ãæå¹ã«ããããšãã§ããŸãã
äŸïŒTypeScriptãš`react-i18next`
ãŸãã翻蚳ãªãœãŒã¹ãTypeScriptã®åãšããŠå®çŸ©ããŸããããã«ããã翻蚳ãããã¡ãã»ãŒãžã®åœ¢ç¶ãå®çŸ©ãããŸãã
// src/i18n/locales/en/translation.d.ts
interface Translation {
greeting: string;
welcomeMessage: string;
userProfile: {
name: string;
age: string;
location: string;
};
// ... other translations
}
export default Translation;
次ã«ããªãœãŒã¹ãå®çŸ©ããåä»ãããŸãã
// src/i18n/locales/en/translation.json
{
"greeting": "Hello",
"welcomeMessage": "Welcome to our website!",
"userProfile": {
"name": "Name: {{name}}",
"age": "Age: {{age}}",
"location": "Location: {{location}}"
}
// ... other translations
}
// src/i18n/i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import translationEN from './locales/en/translation.json';
import translationDE from './locales/de/translation.json';
import Translation from './locales/en/translation'; // Import the type definition
// Define resource types explicitly to ensure type safety
interface Resources {
en: {
translation: typeof translationEN;
};
de: {
translation: typeof translationDE;
};
}
i18n
.use(initReactI18next)
.init({ // Explicitly type i18n.init
resources: {
en: {
translation: translationEN
},
de: {
translation: translationDE
}
},
lng: 'en',
fallbackLng: 'en',
interpolation: {
escapeValue: false
}
});
export default i18n;
æåŸã«ã`useTranslation`ããã¯ã䜿çšããæ£ããåä»ãããŸãã
// src/components/UserProfile.tsx
import React from 'react';
import { useTranslation } from 'react-i18next';
import Translation from '../i18n/locales/en/translation';
interface Props {
name: string;
age: number;
location: string;
}
const UserProfile: React.FC = ({ name, age, location }) => {
const { t } = useTranslation<'translation', undefined, Translation>();
return (
{t('userProfile.name', { name })}
{t('userProfile.age', { age })}
{t('userProfile.location', { location })}
);
};
export default UserProfile;
ãã®ã¢ãããŒãã«ãããããŒã®ã¿ã€ããäžæ£ãªãã©ã¡ãŒã¿ã®äœ¿çšãTypeScriptã³ã³ãã€ã©ã«ãã£ãŠææãããããšãä¿èšŒãããŸãã
2. 翻蚳ãã¡ã€ã«ããã®ã³ãŒãçæ
ããäžã€ã®æŠç¥ã¯ã翻蚳ãã¡ã€ã«ããçŽæ¥TypeScriptã®åã颿°ãçæããããšã§ãããã®ã¢ãããŒãã«ãããã³ãŒããåžžã«ç¿»èš³ãšåæããŠããããšãä¿èšŒãããæåã§åãå®çŸ©ããå¿ èŠããªããªããŸãã`i18next-parser`ã®ãããªããŒã«ãã«ã¹ã¿ã ã¹ã¯ãªããã䜿çšããŠããã®ããã»ã¹ãèªååã§ããŸãã
äŸïŒã³ãŒãçæã¯ãŒã¯ãããŒ
- 翻蚳ãã¡ã€ã«ã®å®çŸ©ïŒ JSONãYAMLãªã©ã®æšæºãã©ãŒãããã§ç¿»èš³ãã¡ã€ã«ãäœæããŸãã
- ã³ãŒãçæããŒã«ã®å®è¡ïŒ ã³ãŒãçæããŒã«ã䜿çšããŠç¿»èš³ãã¡ã€ã«ãè§£æããTypeScriptã®åãšé¢æ°ãçæããŸãã
- çæãããã³ãŒãã®ã€ã³ããŒãïŒ çæãããã³ãŒããã¢ããªã±ãŒã·ã§ã³ã«ã€ã³ããŒãããçæããã颿°ã䜿çšããŠç¿»èš³ã«ã¢ã¯ã»ã¹ããŸãã
ãã®ã¢ãããŒãã¯ããã«ãããã»ã¹ã«çµ±åããŠãçæãããã³ãŒããåžžã«ææ°ã®ç¶æ ã§ããããšãä¿èšŒã§ããŸãã
3. å°çšã®åå®å šãªi18nã©ã€ãã©ãªã®äœ¿çš
äžéšã®ã©ã€ãã©ãªã¯ãåå®å šãªi18nã®ããã«ç¹å¥ã«èšèšãããŠããŸãããããã®ã©ã€ãã©ãªã¯ãçµã¿èŸŒã¿ã®åãã§ãã¯ãšã³ãŒãè£å®ãåããã翻蚳ãå®çŸ©ã»ã¢ã¯ã»ã¹ããããã®æµæ¢ãªAPIãæäŸããŸããi18nãœãªã¥ãŒã·ã§ã³ã®æ§æèŠçŽ ãšããŠãã䜿çšããã`formatjs`ã®ãããªã©ã€ãã©ãªã®æ€èšãèããããŸãã
äŸïŒ`formatjs`ã«ããæŠå¿µçãªæŠèŠ
`formatjs`ã¯æ¬è³ªçã«å®å šãªåå®å šæ§ã匷å¶ããããã§ã¯ãããŸãããããã®äžã«åå®å šãªã¬ã€ã€ãŒãæ§ç¯ããããã®ããŒã«ãæäŸããŸããéåžžãTypeScriptã䜿çšããŠã¡ãã»ãŒãžãã£ã¹ã¯ãªãã¿ãå®çŸ©ãããããã®ãã£ã¹ã¯ãªãã¿ã«åŸã£ãŠã¡ãã»ãŒãžããã©ãŒãããããããã«`formatjs`ã®APIã䜿çšããŸãã
// Define message descriptors with types
interface MessageDescriptor {
id: string;
defaultMessage: string;
description?: string;
}
const messages: {
[key: string]: MessageDescriptor;
} = {
greeting: {
id: 'app.greeting',
defaultMessage: 'Hello, {name}!',
description: 'A simple greeting message',
},
// ... more messages
};
// Use formatMessage with typed messages
import { createIntl, createIntlCache } from '@formatjs/intl';
const cache = createIntlCache();
const intl = createIntl(
{
locale: 'en',
messages: {
[messages.greeting.id]: messages.greeting.defaultMessage,
},
},
{ cache }
);
// Usage
const formattedMessage = intl.formatMessage(messages.greeting, { name: 'John' });
console.log(formattedMessage); // Output: Hello, John!
éèŠãªã®ã¯ãTypeScriptã䜿çšããŠã¡ãã»ãŒãžã®æ§é ãå®çŸ©ãã`formatMessage`ã«æž¡ããã©ã¡ãŒã¿ããããã®å®çŸ©ãšäžèŽããããšãä¿èšŒããããšã§ããããã«ã¯æåã®åã¢ãããŒã·ã§ã³ãå¿ èŠã§ãããè¯å¥œãªã¬ãã«ã®åå®å šãæäŸããŸãã
å®è·µçãªèæ ®äºé
åå®å šãªi18nãå®è£ ããã«ã¯ãããã€ãã®èŠçŽ ãæ éã«èšç»ããèæ ®ããå¿ èŠããããŸãã
1. é©åãªi18nã©ã€ãã©ãªã®éžæ
åå®å šããµããŒããã䜿çšããŠããããã°ã©ãã³ã°èšèªããã¬ãŒã ã¯ãŒã¯ãšããŸãçµ±åã§ããi18nã©ã€ãã©ãªãéžæããŠãã ãããã©ã€ãã©ãªã®æ©èœãããã©ãŒãã³ã¹ãã³ãã¥ããã£ãµããŒããèæ ®ããŸãããã
2. äžè²«ãã翻蚳ããŒæ§é ã®å®çŸ©
翻蚳ããŒã«å¯ŸããŠæç¢ºã§äžè²«ããåœåèŠåã確ç«ããŠãã ãããããã«ãããæéã®çµéãšãšãã«ç¿»èš³ã®ç®¡çãšä¿å®ã容æã«ãªããŸããæ©èœãã¢ãžã¥ãŒã«ããšã«ããŒãæŽçããããã«ãéå±€æ§é ã䜿çšããããšãæ€èšããŠãã ããã
äŸïŒç¿»èš³ããŒã®æ§é
// Feature: User Profile
userProfile.name
userProfile.age
userProfile.location
// Feature: Product Details
productDetails.title
productDetails.description
productDetails.price
3. åçã³ã³ãã³ãã®åãæ±ã
åçã³ã³ãã³ããæ±ãéã«ã¯ã翻蚳ãããŸããŸãªããŒã¿åããã©ãŒãããã«å¯Ÿå¿ã§ããããã«ããŠãã ããããã¬ãŒã¹ãã«ããŒãè£éã䜿çšããŠãåçãªå€ãç¿»èš³ã«æ¿å ¥ããŸãããããã®ãã¬ãŒã¹ãã«ããŒã¯åžžã«åŒ·ãåä»ãããŠãã ããã
4. ãã¹ããšæ€èšŒ
i18nã®å®è£ ãæ£ããæ©èœããŠããããšã確èªããããã«ãå æ¬çãªãã¹ããšæ€èšŒæŠç¥ãå®è£ ããŠãã ãããæœåšçãªåé¡ãç¹å®ããããã«ãããŸããŸãªèšèªãå°åã§ã¢ããªã±ãŒã·ã§ã³ããã¹ãããŸãã翻蚳ãã¡ã€ã«ã®æŽåæ§ãæ€èšŒããããŒã«ã®äœ¿çšãæ€èšããŠãã ããã
5. ç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãšãããã€ã¡ã³ã
i18nã®å®è£ ãç¶ç¶çã€ã³ãã°ã¬ãŒã·ã§ã³ãšãããã€ã¡ã³ãïŒCI/CDïŒãã€ãã©ã€ã³ã«çµ±åããŠãã ãããããã«ãããéçºããã»ã¹ã®æ©ã段éã§ãšã©ãŒãäžæŽåãææãããããã«ãªããŸããCI/CDãã€ãã©ã€ã³å ã§ç¿»èš³ãã¡ã€ã«ããåãçæããããã»ã¹ãèªååããŸãããã
åå®å šãªi18nã®ããã®ãã¹ããã©ã¯ãã£ã¹
- åå®å šãªi18nã©ã€ãã©ãªã䜿çšããïŒ çµã¿èŸŒã¿ã®åå®å šãæäŸããããåã·ã¹ãã ãšå®¹æã«çµ±åã§ããi18nã©ã€ãã©ãªãéžæããŸãã
- 翻蚳ããŒã®TypeScriptåãå®çŸ©ããïŒ ç¿»èš³ããŒãšå€ã衚ãTypeScriptåãäœæããŸãã
- 翻蚳ãã¡ã€ã«ããã³ãŒããçæããïŒ ã³ãŒãçæããŒã«ã䜿çšããŠã翻蚳ãã¡ã€ã«ããèªåçã«TypeScriptã®åãšé¢æ°ãçæããŸãã
- åãã§ãã¯ã匷å¶ããïŒ TypeScriptã®èšå®ã§å³å¯ãªåãã§ãã¯ãæå¹ã«ããã³ã³ãã€ã«æã«ãšã©ãŒãææããŸãã
- åäœãã¹ããäœæããïŒ i18nã®å®è£ ãæ£ããæ©èœããŠããããšãæ€èšŒããããã«åäœãã¹ããäœæããŸãã
- ãªã³ã¿ãŒã䜿çšããïŒ ãªã³ã¿ãŒã䜿çšããŠã³ãŒãã£ã³ã°æšæºã匷å¶ããäžè¬çãªi18nã®ãšã©ãŒãé²ããŸãã
- ããã»ã¹ãèªååããïŒ åã®çæããã¹ããi18nå®è£ ã®ãããã€ã®ããã»ã¹ãèªååããŸãã
çµè«
åå®å šãªåœéåã¯ãå ç¢ã§ä¿å®æ§ã®é«ãå€èšèªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããäžã§éåžžã«éèŠãªåŽé¢ã§ããéçåä»ãã®åãæŽ»çšããããšã§ãäžè¬çãªi18nã®ãšã©ãŒãé²ããéçºè ã®çç£æ§ãåäžãããã³ãŒããžã®ä¿¡é Œæ§ãé«ããããšãã§ããŸããi18nã©ã€ãã©ãªãæ éã«éžæããåãã§ãã¯ãšçµ±åããããšã§ãéçºãåçåããåœéåãããã¢ããªã±ãŒã·ã§ã³ã®å質ãåäžãããããšãã§ããŸãã
ãã®ã¬ã€ãã§ã¯ãåå®å šãªi18nã®å©ç¹ãå®è£ æŠç¥ãå®è·µçãªèæ ®äºé ã«ã€ããŠå æ¬çãªæŠèŠã説æããŸããããããã®ãã¹ããã©ã¯ãã£ã¹ã«åŸãããšã§ãä¿¡é Œæ§ãé«ããä¿å®å¯èœã§ãã¹ã±ãŒã©ãã«ãªi18nå®è£ ãäœæããããšãã§ããŸãã
åèè³æ
- i18next: JavaScriptããã®ä»ã®èšèªã§äººæ°ã®åœéåãã¬ãŒã ã¯ãŒã¯ã
- react-i18next: i18nextã®Reactçµ±åã
- next-i18next: Next.jsçšã®i18nextçµ±åã
- FormatJS: ã¡ãã»ãŒãžãã©ãŒããããæ°å€ãã©ãŒããããæ¥ä»ãã©ãŒããããå«ããåœéåã®ããã®JavaScriptã©ã€ãã©ãªã®ã³ã¬ã¯ã·ã§ã³ã
- TypeScript: éçåä»ãã远å ããJavaScriptã®ã¹ãŒããŒã»ããã