Skip to content

Commit d3af5ac

Browse files
authored
Merge pull request #12006 from ethereum/language-menu
Language picker
2 parents 6436fd1 + 4172a13 commit d3af5ac

38 files changed

+2600
-192
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Update Crowdin translation progression
2+
3+
on:
4+
schedule:
5+
- cron: "20 16 * * FRI"
6+
workflow_dispatch:
7+
8+
jobs:
9+
create_pr:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Check out code
13+
uses: actions/checkout@v3
14+
15+
- name: Set up Node.js
16+
uses: actions/setup-node@v3
17+
with:
18+
node-version: 18
19+
20+
- name: Install dependencies
21+
run: yarn install
22+
23+
- name: Install ts-node
24+
run: yarn global add ts-node
25+
26+
- name: Set up git
27+
run: |
28+
git config --global user.email "[email protected]"
29+
git config --global user.name "GitHub Action"
30+
31+
- name: Generate timestamp and readable date
32+
id: date
33+
run: |
34+
echo "TIMESTAMP=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
35+
echo "READABLE_DATE=$(date +'%B %-d')" >> $GITHUB_ENV
36+
37+
- name: Fetch latest dev and create new branch
38+
run: |
39+
git fetch origin dev
40+
git checkout -b "automated-update-${{ env.TIMESTAMP }}" origin/dev
41+
42+
- name: Run script
43+
run: npx ts-node -O '{"module":"commonjs"}' ./src/scripts/crowdin/getTranslationProgress.ts
44+
env:
45+
CROWDIN_API_KEY: ${{ secrets.CROWDIN_API_KEY }}
46+
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
47+
48+
- name: Commit and push
49+
run: |
50+
git add -A
51+
git commit -m "Update Crowdin translation progress"
52+
git push origin "automated-update-${{ env.TIMESTAMP }}"
53+
54+
- name: Create PR body
55+
run: |
56+
echo "This PR was automatically created to update Crowdin translation progress." > pr_body.txt
57+
echo "This workflows runs every Friday at 16:20 (UTC)." >> pr_body.txt
58+
echo "" >> pr_body.txt
59+
echo "Thank you to everyone contributing to translate ethereum.org ❤️" >> pr_body.txt
60+
61+
- name: Create Pull Request
62+
run: |
63+
gh auth login --with-token <<< ${{ secrets.GITHUB_TOKEN }}
64+
gh pr create --base dev --head "automated-update-${{ env.TIMESTAMP }}" --title "Update translation progress from Crowdin - ${{ env.READABLE_DATE }}" --body-file pr_body.txt

i18n.config.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@
297297
},
298298
{
299299
"code": "ne-np",
300-
"crowdinCode": "ne-np",
300+
"crowdinCode": "ne-NP",
301301
"name": "Nepali",
302302
"localName": "नेपाली",
303303
"langDir": "ltr",
@@ -457,7 +457,7 @@
457457
},
458458
{
459459
"code": "ur",
460-
"crowdinCode": "ur",
460+
"crowdinCode": "ur-IN",
461461
"name": "Urdu",
462462
"localName": "اردو",
463463
"langDir": "rtl",
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { useRouter } from "next/router"
2+
import { useTranslation } from "next-i18next"
3+
import { BsCheck } from "react-icons/bs"
4+
import {
5+
Badge,
6+
Box,
7+
Flex,
8+
forwardRef,
9+
Icon,
10+
MenuItem as ChakraMenuItem,
11+
type MenuItemProps as ChakraMenuItemProps,
12+
Text,
13+
} from "@chakra-ui/react"
14+
15+
import type { LocaleDisplayInfo } from "@/lib/types"
16+
17+
import { BaseLink } from "@/components/Link"
18+
19+
import ProgressBar from "./ProgressBar"
20+
21+
type ItemProps = ChakraMenuItemProps & {
22+
displayInfo: LocaleDisplayInfo
23+
}
24+
25+
const MenuItem = forwardRef(({ displayInfo, ...props }: ItemProps, ref) => {
26+
const {
27+
localeOption,
28+
sourceName,
29+
targetName,
30+
approvalProgress,
31+
wordsApproved,
32+
isBrowserDefault,
33+
} = displayInfo
34+
const { t } = useTranslation("page-languages")
35+
const { asPath, locale } = useRouter()
36+
const isCurrent = localeOption === locale
37+
38+
const getProgressInfo = (approvalProgress: number, wordsApproved: number) => {
39+
const percentage = new Intl.NumberFormat(locale!, {
40+
style: "percent",
41+
}).format(approvalProgress / 100)
42+
const progress =
43+
approvalProgress === 0 ? "<" + percentage.replace("0", "1") : percentage
44+
const words = new Intl.NumberFormat(locale!).format(wordsApproved)
45+
return { progress, words }
46+
}
47+
48+
const { progress, words } = getProgressInfo(approvalProgress, wordsApproved)
49+
50+
return (
51+
<ChakraMenuItem
52+
as={BaseLink}
53+
ref={ref}
54+
flexDir="column"
55+
w="full"
56+
mb="1"
57+
display="block"
58+
pt="2 !important"
59+
alignItems="start"
60+
borderRadius="base"
61+
bg={isCurrent ? "background.base" : "transparent"}
62+
color="body.base"
63+
textDecoration="none"
64+
data-group
65+
onFocus={(e) => {
66+
e.target.scrollIntoView({ block: "nearest" })
67+
}}
68+
scrollMarginY="8"
69+
_hover={{ bg: "primary.lowContrast", textDecoration: "none" }}
70+
_focus={{ bg: "primary.lowContrast" }}
71+
sx={{
72+
p: {
73+
textDecoration: "none",
74+
overflow: "hidden",
75+
textOverflow: "ellipsis",
76+
whiteSpace: "nowrap",
77+
},
78+
}}
79+
href={asPath}
80+
locale={localeOption}
81+
{...props}
82+
>
83+
<Flex alignItems="center" w="full">
84+
<Box flex={1}>
85+
<Flex alignItems="center" gap={2}>
86+
<Text
87+
fontSize="lg"
88+
color={isCurrent ? "primary.highContrast" : "primary.base"}
89+
>
90+
{targetName}
91+
</Text>
92+
{isBrowserDefault && (
93+
<Badge
94+
border="1px"
95+
borderColor="body.medium"
96+
color="body.medium"
97+
lineHeight="none"
98+
fontSize="2xs"
99+
p="1"
100+
h="fit-content"
101+
bg="none"
102+
>
103+
{t("page-languages-browser-default")}
104+
</Badge>
105+
)}
106+
</Flex>
107+
<Text textTransform="uppercase" fontSize="xs" color="body.base">
108+
{sourceName}
109+
</Text>
110+
</Box>
111+
{isCurrent && <Icon as={BsCheck} fontSize="2xl" color="primary.highContrast" />}
112+
</Flex>
113+
<Text
114+
textTransform="lowercase"
115+
fontSize="xs"
116+
color="body.medium"
117+
maxW="full"
118+
>
119+
{progress} {t("page-languages-translated")}{words}{" "}
120+
{t("page-languages-words")}
121+
</Text>
122+
<ProgressBar value={approvalProgress} />
123+
</ChakraMenuItem>
124+
)
125+
})
126+
127+
export default MenuItem
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { useTranslation } from "next-i18next"
2+
import { FormHelperText, forwardRef, Text } from "@chakra-ui/react"
3+
4+
import { BaseLink } from "@/components/Link"
5+
6+
import MenuItem from "./MenuItem"
7+
8+
type NoResultsCalloutProps = { onClose: () => void }
9+
10+
const NoResultsCallout = forwardRef(
11+
({ onClose }: NoResultsCalloutProps, ref) => {
12+
const { t } = useTranslation("page-languages")
13+
return (
14+
<FormHelperText color="body.medium" lineHeight="base" fontSize="md">
15+
<Text fontWeight="bold" mb="2" color="body.base">
16+
{t("page-languages-want-more-header")}
17+
</Text>
18+
{t("page-languages-want-more-paragraph")}{" "}
19+
<BaseLink
20+
ref={ref}
21+
as={MenuItem}
22+
key="item-no-results"
23+
href="contributing/translation-program"
24+
onClick={onClose}
25+
>
26+
{t("page-languages-want-more-link")}
27+
</BaseLink>
28+
</FormHelperText>
29+
)
30+
}
31+
)
32+
33+
export default NoResultsCallout
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Progress, ProgressProps } from "@chakra-ui/react"
2+
3+
type ProgressBarProps = Pick<ProgressProps, "value">
4+
5+
const ProgressBar = ({ value }: ProgressBarProps) => (
6+
<Progress
7+
value={value}
8+
h="0.5"
9+
w="full"
10+
bg="body.light"
11+
sx={{
12+
"[role=progressbar]": {
13+
backgroundColor: "disabled",
14+
},
15+
}}
16+
/>
17+
)
18+
19+
export default ProgressBar

0 commit comments

Comments
 (0)