์๋ก์ด ๊ตญ๊ฐ์ ์ง์ญ์ ๊ฐ์ฒํ๋ ๊ตญ์ ๊ธฐ์
์๊ฒ ์ ํ ํ์งํ๋ ๋งค์ฐ ์ค์ํฉ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๋ชจ๋ฐ์ผ ์ ํ๋ฆฌ์ผ์ด์
์๋ ํ์งํ๊ฐ ํ์ํฉ๋๋ค. ๊ฐ๋ฐ์๊ฐ ํด์ธ ํ์ฅ์ ์์ํ๋ ๊ฒฝ์ฐ ๋ค๋ฅธ ๊ตญ๊ฐ์ ์ฌ์ฉ์์๊ฒ ๋ชจ๊ตญ์ด๋ก ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ธฐํ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ์ด ๊ธฐ์ฌ์์๋ ํจํค์ง๋ฅผ ์ฌ์ฉํ์ฌ React Native ์ ํ๋ฆฌ์ผ์ด์
์ ์์ฑํฉ๋๋ค.
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค. ๊ต์ก์ฉ ์จ๋ผ์ธ ๊ณผ์
"์ง์ ์๋ฐ ๊ฐ๋ฐ์" .
์๋ฆผ: "Habr"์ ๋ชจ๋ ๋ ์๋ฅผ ์ํ - "Habr" ํ๋ก๋ชจ์ ์ฝ๋๋ฅผ ์ฌ์ฉํ์ฌ Skillbox ๊ณผ์ ์ ๋ฑ๋กํ ๋ 10 ๋ฃจ๋ธ ํ ์ธ.
๋๊ตฌ ๋ฐ ๊ธฐ์
์ด ๊ธ์ ์ดํดํ๋ ค๋ฉด React Native ์์
์ ๋ํ ๊ธฐ๋ณธ ๊ธฐ์ ์ด ํ์ํฉ๋๋ค. ์์
๊ธฐ๊ณ์ ์ค์ ์ ์ต์ํด์ง๋ ค๋ฉด ๋ค์์ ์ํํ์ญ์์ค.
๋ค์ ๋ฒ์ ์ ์ํํธ์จ์ด ๋๊ตฌ๊ฐ ํ์ํฉ๋๋ค.
- ๋ ธ๋ v10.15.0
- npm 6.4.1
- ํธ์ค 1.16.0
- ๋ฐ์ ๋ค์ดํฐ๋ธ 0.59.9
- ๋ฐ์ ๋ค์ดํฐ๋ธ ํ์งํ 1.1.3
- i18n-js 3.3.0
ะะฐัะธะฝะฐะตะผ
์์ด, ํ๋์ค์ด, ์๋์ด๋ฅผ ์ง์ํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ง๋ค๊ฒ ์ต๋๋ค. ๋จผ์ React-native-cli๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ก์ ํธ๋ฅผ ์์ฑํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ ค๋ฉด ํฐ๋ฏธ๋์ ๋ค์์ ์ ๋ ฅํด์ผ ํฉ๋๋ค.
$ ๋ฐ์ ๋ค์ดํฐ๋ธ ์ด๊ธฐํ ๋ค๊ตญ์ด
$ cd ๋ค๊ตญ์ด
ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ
์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ๋ค์์ ์
๋ ฅํ์ฌ React-native-localize๋ฅผ ์ค์นํ๋ ๊ฒ์
๋๋ค.
$ ์์ฌ ๋ฐ์ ๋ค์ดํฐ๋ธ ํ์งํ ์ถ๊ฐ
์ค์น ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ,
React-native-localize ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ ๊ฐ๋ฐ์์๊ฒ ๋ค๊ตญ์ด ๊ธฐ๋ฅ์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ์ง๋ง ๊ทธ๋ ์๊ฒ๋ i18n์ด๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ๋ ๋ ํ์ํฉ๋๋ค.
์ด ๋ฌธ์์์๋ ์ฌ์ฉ๋ฒ์ ์ค๋ช
ํฉ๋๋ค.
$ ์์ฌ i18n-js ์ถ๊ฐ
i18n-js๋ ์บ์ฑ์ด๋ ๋ฉ๋ชจ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง ์์ผ๋ฏ๋ก ์ด๋ฅผ ์ํด lodash.memoize๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
$ ์์ฌ lodash.memoize ์ถ๊ฐ
๋ฒ์ญ ์์
์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ค๋ฅธ ์ธ์ด์ ์๋ํ ์ ์์ผ๋ ค๋ฉด ๋จผ์ src ๋ด์ ๋ฒ์ญ ๋๋ ํฐ๋ฆฌ๋ฅผ ๋ง๋ ๋ค์ ๊ฐ ์ธ์ด์ ๋ํ ์ธ ๊ฐ์ JSON ํ์ผ์ ๋ง๋ค์ด์ผ ํฉ๋๋ค.
1. ์์ด์ ๊ฒฝ์ฐ en.json;
2. ํ๋์ค์ด์ ๊ฒฝ์ฐ fr.json;
3. ์๋์ด์ ๊ฒฝ์ฐ ar.json.
์ด๋ฌํ ํ์ผ์๋ ํค์ ๊ฐ์ด ํฌํจ๋ JSON ๊ฐ์ฒด๊ฐ ํฌํจ๋์ด ์์ต๋๋ค. ํค๋ ๊ฐ ์ธ์ด๋ง๋ค ๋์ผํฉ๋๋ค. ์ด๋ ์์ฉ ํ๋ก๊ทธ๋จ์์ ํ ์คํธ ์ ๋ณด๋ฅผ ํ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๊ฐ์ ์ฌ์ฉ์์๊ฒ ํ์๋์ด์ผ ํ๋ ํ ์คํธ์ ๋๋ค.
์์ด:
{"์๋ ํ์ธ์": "์๋ ํ์ธ์!"}
ะคัะฐะฝััะทัะบะธะน
{"์๋ ํ์ธ์": "Salut le Monde!"}
ะัะฐะฑัะบะธะน
{ "์๋ ํ์ธ์": "ุงููุงู ุจุงูุนุงูู "}
๊ฐ์ ๋ฐฉ๋ฒ์ผ๋ก ๋ค๋ฅธ ์ธ์ด๋ ์ถ๊ฐํ ์ ์์ต๋๋ค.
๋ฉ์ธ์ฝ๋
์ด ์์ ์์ App.js ํ์ผ์ ์ด๊ณ ์ฌ๊ธฐ์ ๊ฐ์ ธ์ค๊ธฐ๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค.
import React from "react";
import * as RNLocalize from "react-native-localize";
import i18n from "i18n-js";
import memoize from "lodash.memoize"; // Use for caching/memoize for better performance
import {
I18nManager,
SafeAreaView,
ScrollView,
StyleSheet,
Text,
View
} from "react-native";
๊ทธ ๋ค์์๋ ๋์ค์ ์ ์ฉํ ๋ณด์กฐ ๊ธฐ๋ฅ๊ณผ ์์๊ฐ ์ถ๊ฐ๋ฉ๋๋ค.
const translationGetters = {
// lazy requires (metro bundler does not support symlinks)
ar: () => require("./src/translations/ar.json"),
en: () => require("./src/translations/en.json"),
fr: () => require("./src/translations/fr.json")
};
const translate = memoize(
(key, config) => i18n.t(key, config),
(key, config) => (config ? key + JSON.stringify(config) : key)
);
const setI18nConfig = () => {
// fallback if no available language fits
const fallback = { languageTag: "en", isRTL: false };
const { languageTag, isRTL } =
RNLocalize.findBestAvailableLanguage(Object.keys(translationGetters)) ||
fallback;
// clear translation cache
translate.cache.clear();
// update layout direction
I18nManager.forceRTL(isRTL);
// set i18n-js config
i18n.translations = { [languageTag]: translationGetters[languageTag]() };
i18n.locale = languageTag;
};
์ด์ App ํด๋์ค์ ๊ตฌ์ฑ ์์๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค.
export default class App extends React.Component {
constructor(props) {
super(props);
setI18nConfig(); // set initial config
}
componentDidMount() {
RNLocalize.addEventListener("change", this.handleLocalizationChange);
}
componentWillUnmount() {
RNLocalize.removeEventListener("change", this.handleLocalizationChange);
}
handleLocalizationChange = () => {
setI18nConfig();
this.forceUpdate();
};
render() {
return (
<SafeAreaView style={styles.safeArea}>
<Text style={styles.value}>{translate("hello")}</Text>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
safeArea: {
backgroundColor: "white",
flex: 1,
alignItems: "center",
justifyContent: "center"
},
value: {
fontSize: 18
}
});
์ฒซ ๋ฒ์งธ ์์์ธ setI18nConfig()๋ ์ด๊ธฐ ๊ตฌ์ฑ์ ์ค์ ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์, componentDidMount()์ ์ด๋ฒคํธ ๋ฆฌ์ค๋๋ฅผ ์ถ๊ฐํด์ผ ํฉ๋๋ค. ์ด ์์๋ ์ ๋ฐ์ดํธ๋ฅผ ์์ ํ๊ณ ์ ๋ฐ์ดํธ๊ฐ ๋ฐ์ํ๋ฉด handlerLocalizationChange()๋ฅผ ํธ์ถํฉ๋๋ค.
handlerLocalizationChange() ๋ฉ์๋๋ setI18nConfig() ๋ฐ forceUpdate()๋ฅผ ํ์ฑํํฉ๋๋ค. ๋ณ๊ฒฝ ์ฌํญ์ ๋์ ๋๊ฒ ํ๋ ค๋ฉด ๊ตฌ์ฑ ์์๋ฅผ ๋ ๋๋งํด์ผ ํ๋ฏ๋ก Android ์ฅ์น์ ํ์ํฉ๋๋ค.
๊ทธ๋ฐ ๋ค์ componentWillUnmount() ๋ฉ์๋์์ ์ฒญ์ทจ๋ฅผ ์ ๊ฑฐํด์ผ ํฉ๋๋ค.
๋ง์ง๋ง์ผ๋ก render()๋ ๋ฒ์ญ()์ ์ฌ์ฉํ๊ณ ์ฌ๊ธฐ์ ์ฃผ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ถ๊ฐํ์ฌ hello๋ฅผ ๋ฐํํฉ๋๋ค. ์ด ๋จ๊ณ๋ฅผ ๋ง์น๋ฉด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ด๋ค ์ธ์ด๊ฐ ํ์ํ์ง "์ดํด"ํ๊ณ ๊ทธ ์์ ๋ฉ์์ง๋ฅผ ํ์ํ ์ ์์ต๋๋ค.
์ ํ๋ฆฌ์ผ์ด์ ์ถ์
์ด์ ๋ฒ์ญ์ด ์ด๋ป๊ฒ ์งํ๋๋์ง ํ์ธํ ์๊ฐ์ ๋๋ค.
๋จผ์ ์๋ฎฌ๋ ์ดํฐ๋ ์๋ฎฌ๋ ์ดํฐ์์ ๋ค์์ ์ ๋ ฅํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ์์ํฉ๋๋ค.
$ ๋ฐ์ ๋ค์ดํฐ๋ธ ์คํ iOS
$ ๋ฐ์ ๋ค์ดํฐ๋ธ ์คํ ์๋๋ก์ด๋
๋ค์๊ณผ ๊ฐ์ด ๋ณด์ผ ๊ฒ์
๋๋ค:
์ด์ ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ์ฌ ์ธ์ด๋ฅผ ํ๋์ค์ด๋ก ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
์ฐ๋ฆฌ๋ ์๋์ด์๋ ๋๊ฐ์ ์ผ์ ํฉ๋๋ค. ์ฐจ์ด๋ ์์ต๋๋ค.
์ฌํ๊น์ง๋ ๊ทธ๋ฐ๋๋ก ์๋๋ค.
ํ์ง๋ง ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฒ์ญ์ด ์๋ ์ธ์ด๋ฅผ ๋ฌด์์๋ก ์ ํํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
findBestLanguage์ ์๋ฌด๋ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ ๋ฒ์ญ ์ค์์ ์ต์ ์ ๋ฒ์ญ์ ์ ๊ณตํ๋ ๊ฒ์ ๋๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ธฐ๋ณธ ์ธ์ด๊ฐ ํ์๋ฉ๋๋ค.
์ฐ๋ฆฌ๋ ์ ํ ์ค์ ์ ๋ํด ์ด์ผ๊ธฐํ๊ณ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด iOS ์๋ฎฌ๋ ์ดํฐ์์๋ ์ธ์ด ์์๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์ ํํ ์ธ์ด๊ฐ ๊ธฐ๋ณธ ์ธ์ด๊ฐ ์๋ ๊ฒฝ์ฐ findBestAvailableLanguage๋ ๊ธฐ๋ณธ ์ธ์ด๊ฐ ํ์๋๋๋ก ์ ์๋์ง ์์ ๊ฐ์ ๋ฐํํฉ๋๋ค.
๋ณด๋์ค
React-native-localize์๋ ์๋ง์ ์ธ์ด ์์์ ๋ํ ์ก์ธ์ค๋ฅผ ์ ๊ณตํ๋ API๊ฐ ์์ต๋๋ค. ์ผ์ ์์ํ๊ธฐ ์ ,
์กฐ์ฌ ๊ฒฐ๊ณผ
์์ฉ ํ๋ก๊ทธ๋จ์ ๋ฌธ์ ์์ด ๋ค๊ตญ์ด๋ก ๋ง๋ค ์ ์์ต๋๋ค. React-native-localize๋ ์ฑ์ ์ฌ์ฉ์ ๊ธฐ๋ฐ์ ํ์ฅํ ์ ์๋ ํ๋ฅญํ ์ต์ ์ ๋๋ค.
ํ๋ก์ ํธ ์์ค ์ฝ๋
Skillbox๋ ๋ค์์ ๊ถ์ฅํฉ๋๋ค.
- XNUMX๋ ์ค์ต ์ฝ์ค
"์ ๋ PRO ์น ๊ฐ๋ฐ์์ ๋๋ค" .- ์จ๋ผ์ธ ์ฝ์ค
"์ฒ์๋ถํฐ C# ๊ฐ๋ฐ์" .- ์ค๊ธฐ ์ฝ์ค
"0์์ PRO๋ก์ PHP ๊ฐ๋ฐ์" .
์ถ์ฒ : habr.com