react-i18next 在我的 React Native 项目中没有翻译

问题描述 投票:0回答:1

我开始了一个新的react-native项目,但我看不到我的react-i18next翻译并保持密钥没有错误。

我还注意到我的组件是在我的layout.tsx之前加载的

谢谢您的帮助

这是我的package.json

{
 (...)
  "dependencies": {
    "@expo/vector-icons": "^14.0.2",
    "@react-navigation/native": "^6.0.2",
    "expo": "~51.0.18",
    "expo-constants": "~16.0.2",
    "expo-font": "~12.0.7",
    "expo-linking": "~6.3.1",
    "expo-router": "~3.5.17",
    "expo-splash-screen": "~0.27.5",
    "expo-status-bar": "~1.12.1",
    "expo-system-ui": "~3.0.7",
    "expo-web-browser": "~13.0.3",
    "i18next": "^23.11.5",
    "i18next-browser-languagedetector": "^8.0.0",
    "i18next-http-backend": "^2.5.2",
    "react": "18.2.0",
    "react-dom": "18.2.0",
    "react-i18next": "^14.1.2",
    "react-native": "0.74.3",
    "react-native-gesture-handler": "~2.16.1",
    "react-native-reanimated": "~3.10.1",
    "react-native-safe-area-context": "4.10.1",
    "react-native-screens": "3.31.1",
    "react-native-web": "~0.19.10"
  }
}

我的 i18n 配置文件

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';

import en from '../assets/locales/translation_en_US.json';
import fr from '../assets/locales/translation_fr_FR.json';
import { LangCode } from './LanguageUtils';

const resources = {
  en: {
    translation: en,
  },
  fr: {
    translation: fr,
  },
};

const initalizeI18Next = () => {
  console.log("🚀 ~ initalizeI18Next ~ resources:", resources);

  i18n
    .use(initReactI18next)
    .use(LanguageDetector)
    .init({
      supportedLngs: [LangCode.en, LangCode.fr],
      debug: false,
      resources,
      lng: LangCode.en,
      fallbackLng: LangCode.fr,
      compatibilityJSON: 'v3',
      interpolation: {
        escapeValue: false,
      },
    });
};

export default { initalizeI18Next };

我的 json 与翻译

{
  "welcome": "Welcome!",
  "step_1": "Step 1: Try it",
  "step_2": "Step 2: Explore",
  "step_3": "Step 3: Get a fresh start",
  "login": "Login",
  "edit_file": "Edit",
  "to_see_changes": "to see changes.",
  "press_to_open_dev_tools": "Press to open developer tools.",
  "explore_tab_info": "Tap the Explore tab to learn more about what's included in this starter app.",
  "run_command_reset_project": "When you're ready, run",
  "to_get_fresh_app_dir": "to get a fresh",
  "this_will_move_current_app": "directory. This will move the current",
  "to_app_example": "to"
}

我的实现

import React, { ReactNode, cloneElement, isValidElement } from 'react';

import { Text, type TextProps, StyleSheet } from 'react-native';
import { useTranslation } from 'react-i18next';

import { useThemeColor } from '@/hooks/useThemeColor';

export type ThemedTextProps = TextProps & {
  lightColor?: string;
  darkColor?: string;
  type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
  translate?: boolean;
};

export function ThemedText({
  style,
  lightColor,
  darkColor,
  type = 'default',
  translate = true,
  ...rest
}: ThemedTextProps) {
  const { t } = useTranslation();
  const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');

  const translateChildren = (children: ReactNode): ReactNode => {
    if (typeof children === 'string') {
      return translate ? t(children) : children;
    }

    if (Array.isArray(children)) {
      return React.Children.map(children, translateChildren);
    }

    if (isValidElement(children)) {
      return cloneElement(children, {
        ...children.props,
        children: translateChildren(children.props.children),
      });
    }

    return children;
  };

  const translatedChildren = translateChildren(rest.children);

  return (
    <Text
      style={[
        { color },
        type === 'default' ? styles.default : undefined,
        type === 'title' ? styles.title : undefined,
        type === 'defaultSemiBold' ? styles.defaultSemiBold : undefined,
        type === 'subtitle' ? styles.subtitle : undefined,
        type === 'link' ? styles.link : undefined,
        style,
      ]}
      {...rest}
    >
      {translatedChildren}
    </Text>
  );
}

const styles = StyleSheet.create({
  default: {
    fontSize: 16,
    lineHeight: 24,
  },
  defaultSemiBold: {
    fontSize: 16,
    lineHeight: 24,
    fontWeight: '600',
  },
  title: {
    fontSize: 32,
    fontWeight: 'bold',
    lineHeight: 32,
  },
  subtitle: {
    fontSize: 20,
    fontWeight: 'bold',
  },
  link: {
    lineHeight: 30,
    fontSize: 16,
    color: '#0a7ea4',
  },
});

编辑:

下面这个例子是有效的

import { StyleSheet } from 'react-native';

import { HelloWave } from '@/components/HelloWave';
import { ThemedText } from '@/components/ThemedText';
import { ThemedView } from '@/components/ThemedView';
import { useTranslation } from 'react-i18next';

export default function HomeScreen() {
  const { t } = useTranslation();

  return (
    <ThemedView style={styles.titleContainer}>
      {t('welcome')}
      <HelloWave />
    </ThemedView>
  );
}

const styles = StyleSheet.create({
  titleContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    gap: 8,
  },
  stepContainer: {
    gap: 8,
    marginBottom: 8,
  },
  reactLogo: {
    height: 178,
    width: 290,
    bottom: 0,
    left: 0,
    position: 'absolute',
  },
});
typescript react-native react-i18next
1个回答
0
投票

就我而言,不需要 useEffect 挂钩,我只需在主屏幕中使用

i18n.initalizeI18Next();
© www.soinside.com 2019 - 2024. All rights reserved.