Skip to content

Commit 9d1c1a6

Browse files
committed
fix(mobile): improve i18n for subscription form
1 parent 70527f0 commit 9d1c1a6

File tree

10 files changed

+82
-26
lines changed

10 files changed

+82
-26
lines changed

apps/mobile/src/components/ui/form/Switch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const FormSwitch = ({
3131
}
3232
return (
3333
<View className={"w-full flex-row"}>
34-
<View className="flex-1">
34+
<View className="flex-1 gap-1">
3535
<FormLabel className="pl-1" label={label} optional />
3636
{!!description && (
3737
<Text className="text-secondary-label mb-1 pl-1 text-sm">{description}</Text>

apps/mobile/src/components/ui/form/TextField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const BaseField = ({
3434
...rest
3535
}: TextInputProps & BaseFieldProps & { ref?: React.Ref<TextInput | null> }) => {
3636
return (
37-
<View className="w-full flex-1">
37+
<View className="w-full flex-1 gap-1">
3838
{!!label && <FormLabel className="pl-2.5" label={label} optional={!required} />}
3939
{!!description && (
4040
<Text className="text-secondary-label mb-1 pl-2.5 text-sm">{description}</Text>

apps/mobile/src/modules/feed/FollowFeed.tsx

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { FeedViewType } from "@follow/constants"
22
import { zodResolver } from "@hookform/resolvers/zod"
33
import { useEffect, useState } from "react"
44
import { Controller, useForm } from "react-hook-form"
5+
import { useTranslation } from "react-i18next"
56
import { Text, View } from "react-native"
67
import { useSafeAreaInsets } from "react-native-safe-area-context"
78
import { z } from "zod"
@@ -70,6 +71,8 @@ export function FollowUrl(props: { url: string }) {
7071
}
7172

7273
function FollowImpl(props: { feedId: string }) {
74+
const { t } = useTranslation()
75+
const { t: tCommon } = useTranslation("common")
7376
const { feedId: id } = props
7477

7578
const feed = useFeed(id)
@@ -147,13 +150,13 @@ function FollowImpl(props: { feedId: string }) {
147150
contentContainerStyle={{ paddingBottom: insets.bottom }}
148151
Header={
149152
<NavigationBlurEffectHeaderView
150-
title={`${isSubscribed ? "Edit" : "Follow"} - ${feed?.title}`}
153+
title={`${isSubscribed ? tCommon("words.edit") : tCommon("words.follow")} - ${feed?.title}`}
151154
headerRight={
152155
<HeaderSubmitTextButton
153156
isValid={isValid}
154157
onPress={form.handleSubmit(submit)}
155158
isLoading={isLoading}
156-
label={isSubscribed ? "Save" : "Follow"}
159+
label={isSubscribed ? tCommon("words.save") : tCommon("words.follow")}
157160
/>
158161
}
159162
/>
@@ -174,56 +177,58 @@ function FollowImpl(props: { feedId: string }) {
174177
{/* Group 2 */}
175178
<GroupedInsetListCard className="gap-y-4 p-4">
176179
<FormProvider form={form}>
177-
<View>
180+
<View className="-mx-2.5">
178181
<Controller
179182
name="title"
180183
control={form.control}
181184
render={({ field: { onChange, ref, value } }) => (
182185
<TextField
183-
label="Title"
184-
description="Custom title for this Feed. Leave empty to use the default."
186+
label={t("subscription_form.title")}
187+
description={t("subscription_form.title_description")}
185188
onChangeText={onChange}
186189
value={value}
187190
ref={ref}
191+
wrapperClassName="ml-2.5"
188192
/>
189193
)}
190194
/>
191195
</View>
192196

193-
<View>
197+
<View className="-mx-2.5">
194198
<Controller
195199
name="category"
196200
control={form.control}
197201
render={({ field: { onChange, ref, value } }) => (
198202
<TextField
199-
label="Category"
200-
description="By default, your follows will be grouped by website."
203+
label={t("subscription_form.category")}
204+
description={t("subscription_form.category_description")}
201205
onChangeText={onChange}
202206
value={value || ""}
203207
ref={ref}
208+
wrapperClassName="ml-2.5"
204209
/>
205210
)}
206211
/>
207212
</View>
208213

209-
<View>
214+
<View className="-mx-1">
210215
<Controller
211216
name="isPrivate"
212217
control={form.control}
213218
render={({ field: { onChange, value } }) => (
214219
<FormSwitch
215220
size="sm"
216221
value={value}
217-
label="Private"
218-
description="Private feeds are only visible to you."
222+
label={t("subscription_form.private_follow")}
223+
description={t("subscription_form.private_follow_description")}
219224
onValueChange={onChange}
220225
/>
221226
)}
222227
/>
223228
</View>
224229

225230
<View className="-mx-4">
226-
<FormLabel className="mb-4 pl-5" label="View" optional />
231+
<FormLabel className="mb-4 pl-4" label={t("subscription_form.view")} optional />
227232

228233
<Controller
229234
name="view"

apps/mobile/src/modules/list/FollowList.tsx

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { zodResolver } from "@hookform/resolvers/zod"
33
import { useQuery } from "@tanstack/react-query"
44
import { useEffect } from "react"
55
import { Controller, useForm } from "react-hook-form"
6+
import { useTranslation } from "react-i18next"
67
import { Alert, StyleSheet, Text, View } from "react-native"
78
import { z } from "zod"
89

@@ -57,6 +58,8 @@ const formSchema = z.object({
5758
})
5859

5960
const Impl = (props: { id: string }) => {
61+
const { t } = useTranslation()
62+
const { t: tCommon } = useTranslation("common")
6063
const { id } = props
6164
const list = useList(id)
6265

@@ -146,13 +149,13 @@ const Impl = (props: { id: string }) => {
146149
contentViewClassName="gap-y-4 mt-2"
147150
Header={
148151
<NavigationBlurEffectHeaderView
149-
title={`${isSubscribed ? "Edit" : "Follow"} - ${list?.title}`}
152+
title={`${isSubscribed ? tCommon("words.edit") : tCommon("words.follow")} - ${list?.title}`}
150153
headerRight={
151154
<HeaderSubmitTextButton
152155
isValid={isValid}
153156
onPress={form.handleSubmit(submit)}
154157
isLoading={isLoading}
155-
label={isSubscribed ? "Save" : "Follow"}
158+
label={isSubscribed ? tCommon("words.save") : tCommon("words.follow")}
156159
/>
157160
}
158161
/>
@@ -179,36 +182,37 @@ const Impl = (props: { id: string }) => {
179182
<GroupedInsetListCard className="gap-y-6 px-5 py-4">
180183
<FormProvider form={form}>
181184
<View className="-mx-4">
182-
<FormLabel className="mb-4 pl-5" label="View" optional />
185+
<FormLabel className="mb-4 pl-4" label={t("subscription_form.view")} optional />
183186

184187
<FeedViewSelector readOnly value={list.view} />
185188
</View>
186189

187-
<View>
190+
<View className="-mx-2.5">
188191
<Controller
189192
name="title"
190193
control={form.control}
191194
render={({ field: { onChange, ref, value } }) => (
192195
<TextField
193-
label="Title"
194-
description="Custom title for this Feed. Leave empty to use the default."
196+
label={t("subscription_form.title")}
197+
description={t("subscription_form.title_description")}
195198
onChangeText={onChange}
196199
value={value}
197200
ref={ref}
201+
wrapperClassName="ml-2.5"
198202
/>
199203
)}
200204
/>
201205
</View>
202206

203-
<View>
207+
<View className="-mx-1">
204208
<Controller
205209
name="isPrivate"
206210
control={form.control}
207211
render={({ field: { onChange, value } }) => (
208212
<FormSwitch
209213
value={value}
210-
label="Private"
211-
description="Private feeds are only visible to you."
214+
label={t("subscription_form.private_follow")}
215+
description={t("subscription_form.private_follow_description")}
212216
onValueChange={onChange}
213217
size="sm"
214218
/>

apps/mobile/src/modules/screen/atoms.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export const useSelectedFeedTitle = () => {
145145
return viewDef?.name ? t(viewDef.name) : ""
146146
}
147147
case "feed": {
148-
return selectedFeed.feedId === FEED_COLLECTION_LIST ? "Collections" : (feed?.title ?? "")
148+
return selectedFeed.feedId === FEED_COLLECTION_LIST ? t("words.starred") : (feed?.title ?? "")
149149
}
150150
case "category": {
151151
return selectedFeed.categoryName

locales/mobile/default/en.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@
5050
"operation.unstar": "Unstar",
5151
"profile.title": "{{name}}'s Profile",
5252
"profile.uncategorized_feeds": "Uncategorized feeds",
53+
"subscription_form.category": "Category",
54+
"subscription_form.category_description": "By default, your follows will be grouped by website.",
55+
"subscription_form.private_follow": "Private Follow",
56+
"subscription_form.private_follow_description": "Whether this follow is publicly visible on your profile page.",
57+
"subscription_form.title": "Title",
58+
"subscription_form.title_description": "Custom title for this Feed. Leave empty to use the default.",
59+
"subscription_form.view": "View",
5360
"tabs.discover": "Discover",
5461
"tabs.home": "Home",
5562
"tabs.settings": "Settings",

locales/mobile/default/ja.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@
3636
"operation.unfollow": "フォロー解除",
3737
"profile.title": "{{name}}のプロフィール",
3838
"profile.uncategorized_feeds": "未分類のフィード",
39+
"subscription_form.category": "カテゴリー",
40+
"subscription_form.category_description": "デフォルトでは、フォローはウェブサイトごとにグループ化されます。",
41+
"subscription_form.private_follow": "プライベートフォロー",
42+
"subscription_form.private_follow_description": "このフォローがあなたのプロフィールページに公開されるかどうか。",
43+
"subscription_form.title": "タイトル",
44+
"subscription_form.title_description": "このフィードのカスタムタイトル。デフォルトを使用するには空白のままにしてください。",
45+
"subscription_form.view": "表示",
3946
"tabs.discover": "発見",
4047
"tabs.home": "ホーム",
4148
"tabs.settings": "設定",

locales/mobile/default/zh-CN.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
"onboarding.welcome_title": "欢迎使用 Folo!",
2424
"operation.add_feeds_to_category": "移动至分类",
2525
"operation.change_to_other_view": "更改为其他视图",
26+
"operation.copy.link": "链接",
27+
"operation.copy_which": "复制{{which}}",
28+
"operation.copy_which_success": "{{which}}已复制到剪贴板",
2629
"operation.delete_category": "删除分类",
2730
"operation.edit": "编辑",
2831
"operation.error_since": "源失效:",
@@ -46,6 +49,13 @@
4649
"operation.unstar": "取消收藏",
4750
"profile.title": "{{name}}的个人资料",
4851
"profile.uncategorized_feeds": "未分类的订阅源",
52+
"subscription_form.category": "分类",
53+
"subscription_form.category_description": "默认情况下,你的订阅将按网站域名分组。",
54+
"subscription_form.private_follow": "私密订阅",
55+
"subscription_form.private_follow_description": "开启后,此订阅不再显示在个人资料页面。",
56+
"subscription_form.title": "标题",
57+
"subscription_form.title_description": "此订阅源的自定义标题,留空则使用默认标题。",
58+
"subscription_form.view": "视图",
4959
"tabs.discover": "发现",
5060
"tabs.home": "首页",
5161
"tabs.settings": "设置",

locales/mobile/default/zh-TW.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,13 @@
4545
"operation.unstar": "取消收藏",
4646
"profile.title": "{{name}} 的個人資料",
4747
"profile.uncategorized_feeds": "未分類的 RSS 摘要",
48+
"subscription_form.category": "類別",
49+
"subscription_form.category_description": "預設情況下,您的跟隨將按網站域名分組。",
50+
"subscription_form.private_follow": "私人跟隨",
51+
"subscription_form.private_follow_description": "啟用後,此跟隨將不再顯示於個人資料頁面上。",
52+
"subscription_form.title": "標題",
53+
"subscription_form.title_description": "此 RSS 摘要的自定義標題。留空以使用預設標題。",
54+
"subscription_form.view": "視圖",
4855
"tabs.discover": "探索",
4956
"tabs.home": "首頁",
5057
"tabs.settings": "設定",

scripts/copy-translation.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,24 @@ import path from "node:path"
33

44
const sourceDir = "./locales/app"
55
const targetDir = "./locales/mobile/default"
6-
const keysToCopy: string[] = ["feed_item.error_since"]
7-
const keysToPlace = ["operation.error_since"]
6+
const keysToCopy: string[] = [
7+
"feed_form.title",
8+
"feed_form.title_description",
9+
"feed_form.category",
10+
"feed_form.category_description",
11+
"feed_form.private_follow",
12+
"feed_form.private_follow_description",
13+
"feed_form.view",
14+
]
15+
const keysToPlace = [
16+
"subscription_form.title",
17+
"subscription_form.title_description",
18+
"subscription_form.category",
19+
"subscription_form.category_description",
20+
"subscription_form.private_follow",
21+
"subscription_form.private_follow_description",
22+
"subscription_form.view",
23+
]
824

925
const copyTranslations = (sourceDir: string, targetDir: string) => {
1026
const sourceFiles = fs.readdirSync(sourceDir)

0 commit comments

Comments
 (0)