diff --git a/README.md b/README.md index 2420f572..c4c48d1b 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,12 @@ ## Special thanks -@forenta for German translation +[@forenta](https://github.com/forenta) for German translation -@andrigamerita for Italian translation +[@andrigamerita](https://github.com/andrigamerita) for Italian translation -@hellojaccc for Korean translation +[@hellojaccc](https://github.com/hellojaccc) for Korean translation -@duy@mas.to for Vietnamese translation \ No newline at end of file +[@luizpicolo](https://github.com/luizpicolo) for Brazilian Portuguese + +[@duy@mas.to](https://mas.to/@duy) for Vietnamese translation diff --git a/package.json b/package.json index 067c070b..f966803b 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "native": "220508", "major": 4, "minor": 0, - "patch": 3, + "patch": 4, "expo": "45.0.0" }, "description": "tooot app for Mastodon", diff --git a/src/App.tsx b/src/App.tsx index bdf6569a..d0344016 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,31 +1,4 @@ import { ActionSheetProvider } from '@expo/react-native-action-sheet' -import '@formatjs/intl-getcanonicallocales/polyfill' -import '@formatjs/intl-locale/polyfill' -import '@formatjs/intl-pluralrules/polyfill' -import '@formatjs/intl-pluralrules/locale-data/de' -import '@formatjs/intl-pluralrules/locale-data/en' -import '@formatjs/intl-pluralrules/locale-data/ko' -import '@formatjs/intl-pluralrules/locale-data/vi' -import '@formatjs/intl-pluralrules/locale-data/zh' -import '@formatjs/intl-numberformat/polyfill' -import '@formatjs/intl-numberformat/locale-data/de' -import '@formatjs/intl-numberformat/locale-data/en' -import '@formatjs/intl-numberformat/locale-data/ko' -import '@formatjs/intl-numberformat/locale-data/vi' -import '@formatjs/intl-numberformat/locale-data/zh' -import '@formatjs/intl-datetimeformat/polyfill' -import '@formatjs/intl-datetimeformat/locale-data/de' -import '@formatjs/intl-datetimeformat/locale-data/en' -import '@formatjs/intl-datetimeformat/locale-data/ko' -import '@formatjs/intl-datetimeformat/locale-data/vi' -import '@formatjs/intl-datetimeformat/locale-data/zh' -import '@formatjs/intl-datetimeformat/add-all-tz' -import '@formatjs/intl-relativetimeformat/polyfill' -import '@formatjs/intl-relativetimeformat/locale-data/de' -import '@formatjs/intl-relativetimeformat/locale-data/en' -import '@formatjs/intl-relativetimeformat/locale-data/ko' -import '@formatjs/intl-relativetimeformat/locale-data/vi' -import '@formatjs/intl-relativetimeformat/locale-data/zh' import queryClient from '@helpers/queryClient' import i18n from '@root/i18n/i18n' import Screens from '@root/Screens' diff --git a/src/components/Menu/Row.tsx b/src/components/Menu/Row.tsx index f53d562c..98c48d14 100644 --- a/src/components/Menu/Row.tsx +++ b/src/components/Menu/Row.tsx @@ -22,7 +22,7 @@ export interface Props { switchDisabled?: boolean switchOnValueChange?: () => void - iconBack?: 'ChevronRight' | 'ExternalLink' + iconBack?: 'ChevronRight' | 'ExternalLink' | 'Check' iconBackColor?: ColorDefinitions loading?: boolean diff --git a/src/i18n/en/screens/tabs.json b/src/i18n/en/screens/tabs.json index 2f240322..cb658c5d 100644 --- a/src/i18n/en/screens/tabs.json +++ b/src/i18n/en/screens/tabs.json @@ -43,6 +43,9 @@ "fontSize": { "name": "Toot Font Size" }, + "language": { + "name": "Language" + }, "lists": { "name": "Lists" }, @@ -221,7 +224,7 @@ } }, "language": { - "heading": "Language", + "heading": "$t(me.stacks.language.name)", "options": { "cancel": "$t(common:buttons.cancel)" } diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 220124af..4df213d7 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -5,9 +5,42 @@ import de from '@root/i18n/de/_all' import en from '@root/i18n/en/_all' import it from '@root/i18n/it/_all' import ko from '@root/i18n/ko/_all' +import pt_BR from '@root/i18n/pt_BR/_all' import vi from '@root/i18n/vi/_all' import zh_Hans from '@root/i18n/zh-Hans/_all' +import '@formatjs/intl-getcanonicallocales/polyfill' +import '@formatjs/intl-locale/polyfill' +import '@formatjs/intl-pluralrules/polyfill' +import '@formatjs/intl-pluralrules/locale-data/de' +import '@formatjs/intl-pluralrules/locale-data/en' +import '@formatjs/intl-pluralrules/locale-data/ko' +import '@formatjs/intl-pluralrules/locale-data/pt' +import '@formatjs/intl-pluralrules/locale-data/vi' +import '@formatjs/intl-pluralrules/locale-data/zh' +import '@formatjs/intl-numberformat/polyfill' +import '@formatjs/intl-numberformat/locale-data/de' +import '@formatjs/intl-numberformat/locale-data/en' +import '@formatjs/intl-numberformat/locale-data/ko' +import '@formatjs/intl-numberformat/locale-data/pt' +import '@formatjs/intl-numberformat/locale-data/vi' +import '@formatjs/intl-numberformat/locale-data/zh-Hans' +import '@formatjs/intl-datetimeformat/polyfill' +import '@formatjs/intl-datetimeformat/locale-data/de' +import '@formatjs/intl-datetimeformat/locale-data/en' +import '@formatjs/intl-datetimeformat/locale-data/ko' +import '@formatjs/intl-datetimeformat/locale-data/pt' +import '@formatjs/intl-datetimeformat/locale-data/vi' +import '@formatjs/intl-datetimeformat/locale-data/zh-Hans' +import '@formatjs/intl-datetimeformat/add-all-tz' +import '@formatjs/intl-relativetimeformat/polyfill' +import '@formatjs/intl-relativetimeformat/locale-data/de' +import '@formatjs/intl-relativetimeformat/locale-data/en' +import '@formatjs/intl-relativetimeformat/locale-data/ko' +import '@formatjs/intl-relativetimeformat/locale-data/pt' +import '@formatjs/intl-relativetimeformat/locale-data/vi' +import '@formatjs/intl-relativetimeformat/locale-data/zh-Hans' + i18n.use(initReactI18next).init({ lng: 'en', fallbackLng: 'en', @@ -15,7 +48,7 @@ i18n.use(initReactI18next).init({ ns: ['common'], defaultNS: 'common', - resources: { 'zh-Hans': zh_Hans, vi, ko, it, en, de }, + resources: { 'zh-Hans': zh_Hans, vi, 'pt-BR': pt_BR, ko, it, en, de }, returnEmptyString: false, saveMissing: true, diff --git a/src/i18n/locales.ts b/src/i18n/locales.ts index 37c27a79..d9d4f560 100644 --- a/src/i18n/locales.ts +++ b/src/i18n/locales.ts @@ -3,6 +3,7 @@ const LOCALES = { en: 'English', it: 'Italiano', ko: '한국어', + 'pt-BR': 'Português (Brasil)', vi: 'Tiếng Việt', 'zh-Hans': '简体中文' } diff --git a/src/i18n/pt_BR/_all.ts b/src/i18n/pt_BR/_all.ts new file mode 100644 index 00000000..fa81be2e --- /dev/null +++ b/src/i18n/pt_BR/_all.ts @@ -0,0 +1,17 @@ +export default { + common: require('./common'), + + screens: require('./screens'), + screenActions: require('./screens/actions'), + screenAnnouncements: require('./screens/announcements'), + screenCompose: require('./screens/compose'), + screenImageViewer: require('./screens/imageViewer'), + screenTabs: require('./screens/tabs'), + + componentEmojis: require('./components/emojis'), + componentInstance: require('./components/instance'), + componentMediaSelector: require('./components/mediaSelector'), + componentParse: require('./components/parse'), + componentRelationship: require('./components/relationship'), + componentTimeline: require('./components/timeline') +} diff --git a/src/screens/Tabs/Me.tsx b/src/screens/Tabs/Me.tsx index 17e1feb1..27ffcc1f 100644 --- a/src/screens/Tabs/Me.tsx +++ b/src/screens/Tabs/Me.tsx @@ -14,6 +14,7 @@ import TabMePush from './Me/Push' import TabMeRoot from './Me/Root' import TabMeSettings from './Me/Settings' import TabMeSettingsFontsize from './Me/SettingsFontsize' +import TabMeSettingsLanguage from './Me/SettingsLanguage' import TabMeSwitch from './Me/Switch' import TabSharedRoot from './Shared/Root' @@ -152,6 +153,19 @@ const TabMe = React.memo( headerLeft: () => navigation.pop(1)} /> })} /> + ({ + title: t('me.stacks.language.name'), + ...(Platform.OS === 'android' && { + headerCenter: () => ( + + ) + }), + headerLeft: () => navigation.pop(1)} /> + })} + /> { const navigation = useNavigation() const dispatch = useAppDispatch() const { showActionSheetWithOptions } = useActionSheet() - const { mode } = useTheme() const { t, i18n } = useTranslation('screenTabs') - const instances = useSelector(getInstances, () => true) const settingsFontsize = useSelector(getSettingsFontsize) const settingsTheme = useSelector(getSettingsTheme) const settingsDarkTheme = useSelector(getSettingsDarkTheme) @@ -49,102 +41,14 @@ const SettingsApp: React.FC = () => { `me.settings.fontsize.content.${mapFontsizeToName(settingsFontsize)}` )} iconBack='ChevronRight' - onPress={() => { - navigation.navigate('Tab-Me-Settings-Fontsize') - }} + onPress={() => navigation.navigate('Tab-Me-Settings-Fontsize')} /> { - const options = Object.keys(LOCALES) - // @ts-ignore - .map(locale => LOCALES[locale]) - .concat(t('me.settings.language.options.cancel')) - - showActionSheetWithOptions( - { - title: t('me.settings.language.heading'), - options, - cancelButtonIndex: options.length - 1, - userInterfaceStyle: mode - }, - buttonIndex => { - if (buttonIndex === undefined) return - if (buttonIndex < options.length - 1) { - analytics('settings_language_press', { - current: i18n.language, - new: options[buttonIndex] - }) - haptics('Success') - - // @ts-ignore - dispatch(changeLanguage(Object.keys(LOCALES)[buttonIndex])) - i18n.changeLanguage(Object.keys(LOCALES)[buttonIndex]) - - // Update Android notification channel language - if (Platform.OS === 'android') { - instances.forEach(instance => { - const accountFull = `@${instance.account.acct}@${instance.uri}` - if (instance.push.decode.value === false) { - Notifications.setNotificationChannelAsync( - `${accountFull}_default`, - { - groupId: accountFull, - name: t('me.push.default.heading'), - ...androidDefaults - } - ) - } else { - Notifications.setNotificationChannelAsync( - `${accountFull}_follow`, - { - groupId: accountFull, - name: t('me.push.follow.heading'), - ...androidDefaults - } - ) - Notifications.setNotificationChannelAsync( - `${accountFull}_favourite`, - { - groupId: accountFull, - name: t('me.push.favourite.heading'), - ...androidDefaults - } - ) - Notifications.setNotificationChannelAsync( - `${accountFull}_reblog`, - { - groupId: accountFull, - name: t('me.push.reblog.heading'), - ...androidDefaults - } - ) - Notifications.setNotificationChannelAsync( - `${accountFull}_mention`, - { - groupId: accountFull, - name: t('me.push.mention.heading'), - ...androidDefaults - } - ) - Notifications.setNotificationChannelAsync( - `${accountFull}_poll`, - { - groupId: accountFull, - name: t('me.push.poll.heading'), - ...androidDefaults - } - ) - } - }) - } - } - } - ) - }} + onPress={() => navigation.navigate('Tab-Me-Settings-Language')} /> + +> = () => { + const { i18n, t } = useTranslation('screenTabs') + const languages = Object.entries(LOCALES) + const instances = useSelector(getInstances) + const dispatch = useDispatch() + + const change = (lang: string) => { + analytics('settings_language_press', { + current: i18n.language, + new: lang + }) + haptics('Success') + + dispatch(changeLanguage(lang)) + i18n.changeLanguage(lang) + + // Update Android notification channel language + if (Platform.OS === 'android') { + instances.forEach(instance => { + const accountFull = `@${instance.account.acct}@${instance.uri}` + if (instance.push.decode.value === false) { + Notifications.setNotificationChannelAsync(`${accountFull}_default`, { + groupId: accountFull, + name: t('me.push.default.heading'), + ...androidDefaults + }) + } else { + Notifications.setNotificationChannelAsync(`${accountFull}_follow`, { + groupId: accountFull, + name: t('me.push.follow.heading'), + ...androidDefaults + }) + Notifications.setNotificationChannelAsync( + `${accountFull}_favourite`, + { + groupId: accountFull, + name: t('me.push.favourite.heading'), + ...androidDefaults + } + ) + Notifications.setNotificationChannelAsync(`${accountFull}_reblog`, { + groupId: accountFull, + name: t('me.push.reblog.heading'), + ...androidDefaults + }) + Notifications.setNotificationChannelAsync(`${accountFull}_mention`, { + groupId: accountFull, + name: t('me.push.mention.heading'), + ...androidDefaults + }) + Notifications.setNotificationChannelAsync(`${accountFull}_poll`, { + groupId: accountFull, + name: t('me.push.poll.heading'), + ...androidDefaults + }) + } + }) + } + } + + return ( + + { + return ( + item[0] !== i18n.language && change(item[0])} + /> + ) + }} + /> + + ) +} + +export default TabMeSettingsLanguage diff --git a/src/utils/navigation/navigators.ts b/src/utils/navigation/navigators.ts index aa940756..5e978256 100644 --- a/src/utils/navigation/navigators.ts +++ b/src/utils/navigation/navigators.ts @@ -146,6 +146,7 @@ export type TabMeStackParamList = { 'Tab-Me-Push': undefined 'Tab-Me-Settings': undefined 'Tab-Me-Settings-Fontsize': undefined + 'Tab-Me-Settings-Language': undefined 'Tab-Me-Switch': undefined } & TabSharedStackParamList export type TabMeStackScreenProps =