Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f38e4f7
Add i18n ESLint plugin configuration
snomiao Aug 18, 2025
9cc24ef
Setup eslint-plugin-i18n-json for internationalization linting
snomiao Aug 18, 2025
b931626
format: Apply prettier --fix changes
snomiao Aug 18, 2025
b4d07c4
Fix: Use @spaced-out/eslint-plugin-i18n instead of eslint-plugin-i18n…
snomiao Aug 19, 2025
46af3d1
feat: Update ESLint config to use @spaced-out/eslint-plugin-i18n
snomiao Aug 19, 2025
45959c3
feat: Apply @spaced-out/eslint-plugin-i18n fixes
snomiao Aug 19, 2025
9b20f24
format: Apply prettier --fix changes
snomiao Aug 19, 2025
9e2df85
feat(NodeStatusBadge): integrate useNextTranslation hook for internat…
snomiao Aug 21, 2025
1c0076a
refactor(Container.stories.tsx): extract inline children components i…
snomiao Aug 21, 2025
8f8fe98
fix(RegistryStory.tsx): update translation keys to use consistent for…
snomiao Aug 21, 2025
a6cb99e
style(LanguageSwitcher.tsx): remove unnecessary template literals aro…
snomiao Aug 21, 2025
1440599
feat(authAdmin.tsx): integrate useNextTranslation hook for improved i…
snomiao Aug 21, 2025
7841ff4
refactor: improve i18n by using interpolation instead of string conca…
snomiao Aug 21, 2025
4afa2d8
refactor: clean up i18n ESLint plugin configuration and remove duplic…
snomiao Aug 21, 2025
72b8f49
refactor: simplify static-label-pairing to use only CommonJS format
snomiao Aug 21, 2025
be0f126
fix: resolve ESLint i18n errors in build
snomiao Sep 22, 2025
f7232e4
format: Apply prettier --fix changes
snomiao Sep 22, 2025
0281ed9
fix: resolve remaining PR review comments
snomiao Sep 22, 2025
8d29fc4
fix: remove duplicate symbolic links
snomiao Sep 23, 2025
c43cdd4
Merge main into sno-i18n-eslint
snomiao Oct 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .eslintrc.json

This file was deleted.

24 changes: 24 additions & 0 deletions .eslintrc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
extends:
- next/core-web-vitals
- plugin:storybook/recommended
- prettier # Should be last to override eslint config.

plugins:
- '@spaced-out/i18n'

rules:
prefer-template: warn
jsx-a11y/alt-text: 'off'
'@spaced-out/i18n/no-static-labels': error

# gradually enable below
# "@spaced-out/i18n/missing-translation": warn
# "@spaced-out/i18n/invalid-translation-key-format": error
# "@spaced-out/i18n/no-react-i18next-import": error
# "@spaced-out/i18n/no-dynamic-labels": error
# "@spaced-out/i18n/i18n-enforce-makeKey-wrapper": error

# not used
# "@spaced-out/i18n/require-flow-pragma": error
# "@spaced-out/i18n/no-undef-no-flow": error
# "no-undef": "off" # Disable core rule when using no-undef-no-flow
321 changes: 189 additions & 132 deletions bun.lock

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion components/AccessTokens/CopyAccessKeyModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ export const CopyAccessTokenModal: React.FC<CopyAccessTokenModalProps> = ({
</p>

<div className="grid grid-cols-8 gap-2 w-full max-w-[23rem]">
<label className="sr-only">Label</label>
<label className="sr-only">
{t('Label', 'Label')}
</label>
<input
id="npm-install"
type="text"
Expand Down
10 changes: 7 additions & 3 deletions components/DeveloperRegistry/DrCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ const DrCard = () => {
return (
<Card className="bg-gray-800 lg:mt-20 xs:mt-4">
<h2 className="text-2xl font-bold tracking-tight text-white">
NodesOrg
{t('NodesOrg', 'NodesOrg')}
</h2>
<p className="mb-2 text-sm text-gray-400">{t('Created')} 5/20/24</p>
<p className="text-sm font-bold text-gray-300 ">{t('MEMBERS')}</p>
<p className="text-sm text-gray-400 ">Robin Huang</p>
<p className="text-sm text-gray-400">Yoland Yan</p>
<p className="text-sm text-gray-400 ">
{t('Robin_Huang', 'Robin Huang')}
</p>
<p className="text-sm text-gray-400">
{t('Yoland_Yan', 'Yoland Yan')}
</p>
<div className="flex items-center justify-center">
{' '}
<Button color="blue" className="w-full ">
Expand Down
6 changes: 5 additions & 1 deletion components/NodeStatusBadge.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Badge } from 'flowbite-react'
import { NodeVersionStatus } from '@/src/api/generated'
import { NodeVersionStatusToReadable } from 'src/mapper/nodeversion'
import { useNextTranslation } from '@/src/hooks/i18n'

export function NodeStatusBadge({
status,
Expand All @@ -9,6 +10,7 @@ export function NodeStatusBadge({
status: NodeVersionStatus
count?: number
}) {
const { t } = useNextTranslation()
return (
<Badge
color={
Expand All @@ -23,7 +25,9 @@ export function NodeStatusBadge({
{NodeVersionStatusToReadable({
status: status as NodeVersionStatus,
})}
{count != null ? <span> x{count}</span> : null}
{count != null && (
<span> {t('×{{count}}', '×{{count}}', { count })}</span>
)}
</Badge>
)
}
16 changes: 10 additions & 6 deletions components/NodeStatusReason.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ export function NodeStatusReason(nv: NodeVersion) {
nv.status_reason
).data?.batchId && (
<span className="ml-2 text-xs text-gray-500">
[Batch:{' '}
[{t('Batch', 'Batch')}:
{
zStatusReason.safeParse(
nv.status_reason
Expand All @@ -374,7 +374,7 @@ export function NodeStatusReason(nv: NodeVersion) {
)}
{!!problemsSummary?.length && (
<>
<h4>{'Problems Summary: '}</h4>
<h4>{t('Problems Summary', 'Problems Summary')}: </h4>
<ol className="ml-4 overflow-x-auto">
{problemsSummary.map((e, i) => (
<li
Expand Down Expand Up @@ -402,7 +402,9 @@ export function NodeStatusReason(nv: NodeVersion) {
{(e.file_path?.length ?? 0) > 18 + 2
? `…${e.file_path?.slice(-18)}`
: e.file_path}
&nbsp;L{e.line_number}
{t('L{{number}}', 'L{{number}}', {
number: e.line_number,
})}
</code>
</div>
<code className="flex-1 ml-4 whitespace-nowrap text">
Expand All @@ -418,7 +420,7 @@ export function NodeStatusReason(nv: NodeVersion) {
)}
{!!code?.trim() && (
<details open={!problemsSummary}>
<summary>{'Status Reason: '}</summary>
<summary>{t('Status Reason', 'Status Reason')}: </summary>
{fullfilledIssueList ? (
<PrettieredYamlDiffView
original={lastCode}
Expand Down Expand Up @@ -450,6 +452,7 @@ export function PrettieredJSON5({ children: raw }: { children: string }) {

export function PrettieredYAML({ children: raw }: { children: string }) {
const { ref, inView } = useInView()
const { t } = useNextTranslation()

const parsedYaml = tryCatch(
(raw: string) => yaml.stringify(yaml.parse(raw)),
Expand Down Expand Up @@ -480,7 +483,7 @@ export function PrettieredYAML({ children: raw }: { children: string }) {
color={'gray'}
>
<MdEdit className="w-5 h-5" />
Toggle Editor
{t('Toggle_Editor', 'Toggle Editor')}
</Button>
</div>
)}
Expand Down Expand Up @@ -517,6 +520,7 @@ export function PrettieredYamlDiffView({
modified: string
}) {
const { ref, inView } = useInView()
const { t } = useNextTranslation()

const parsedModified = tryCatch(
(raw: string) => raw && yaml.stringify(yaml.parse(raw)),
Expand Down Expand Up @@ -559,7 +563,7 @@ export function PrettieredYamlDiffView({
color={'gray'}
>
<MdEdit className="w-5 h-5" />
Toggle Editor
{t('Toggle_Editor', 'Toggle Editor')}
</Button>
</div>
)}
Expand Down
9 changes: 7 additions & 2 deletions components/Search/Autocomplete.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { usePagination, useSearchBox } from 'react-instantsearch'
import { debounce } from '@algolia/autocomplete-shared'

import { INSTANT_SEARCH_QUERY_SUGGESTIONS } from 'src/constants'
import { useNextTranslation } from '@/src/hooks/i18n'

import '@algolia/autocomplete-theme-classic'

Expand All @@ -42,6 +43,7 @@ export default function Autocomplete({
const rootRef = useRef<HTMLElement | null>(null)

const { query, refine: setQuery } = useSearchBox()
const { t } = useNextTranslation()

const { refine: setPage } = usePagination()

Expand Down Expand Up @@ -105,7 +107,10 @@ export default function Autocomplete({
return (
<Fragment>
<span className="aa-SourceHeaderTitle">
In other categories
{t(
'In_other_categories',
'In other categories'
)}
</span>
<span className="aa-SourceHeaderLine" />
</Fragment>
Expand All @@ -117,7 +122,7 @@ export default function Autocomplete({
})

return [recentSearches, querySuggestions]
}, [searchClient])
}, [searchClient, t])

useEffect(() => {
if (!autocompleteContainer.current) {
Expand Down
22 changes: 17 additions & 5 deletions components/Search/SearchHit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,14 @@ const Hit: React.FC<HitProps> = ({ hit }) => {
>
{matchedNodes?.length ? (
<>
{matchedNodes?.length ?? 0}/
{hit.comfy_nodes?.length ?? 0} Nodes
matched:
{t(
'{{matched}}/{{total}} Nodes matched:',
'{{matched}}/{{total}} Nodes matched:',
{
matched: matchedNodes?.length ?? 0,
total: hit.comfy_nodes?.length ?? 0,
}
)}
{matchedNodes
?.map((e) =>
e.value?.replace(/<\/?mark>/g, '**')
Expand All @@ -90,7 +95,11 @@ const Hit: React.FC<HitProps> = ({ hit }) => {
))}
</>
) : (
<>{hit.comfy_nodes?.length ?? 0} Nodes</>
<>
{t('{{count}} Nodes', '{{count}} Nodes', {
count: hit.comfy_nodes?.length ?? 0,
})}
</>
)}
</Tooltip>
</div>
Expand All @@ -105,7 +114,10 @@ const Hit: React.FC<HitProps> = ({ hit }) => {
{hit.latest_version && (
<span className="">
{' | '}
<span>v{hit.latest_version}</span>
<span>
{t('v', 'v')}
{hit.latest_version}
</span>
</span>
)}
{hit.total_install && (
Expand Down
10 changes: 7 additions & 3 deletions components/admin/NodeVersionCompatibilityEditModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -219,10 +219,14 @@ export default function NodeVersionCompatibilityEditModal({
<div className="flex items-center justify-between">
<div className="font-semibold">
{t(
'Latest Version Compatibility Reference'
'Latest Version Compatibility Reference: v{{version}}',
{
version:
nodeData
.latest_version
.version,
}
)}
:{' '}
{`v${nodeData.latest_version.version}`}
</div>
<Button
size="xs"
Expand Down
9 changes: 8 additions & 1 deletion components/common/HOC/authAdmin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect } from 'react'
import { useGetUser } from '@/src/api/generated'
import { useFirebaseUser } from '@/src/hooks/useFirebaseUser'
import { useFromUrlParam } from './useFromUrl'
import { useNextTranslation } from '@/src/hooks/i18n'

/**
* Admin dashboard HOC
Expand All @@ -17,6 +18,7 @@ const withAdmin = (WrappedComponent) => {
const HOC = (props: JSX.IntrinsicAttributes) => {
const router = useRouter()
const fromUrlParam = useFromUrlParam()
const { t } = useNextTranslation()

// if firebaseUser is signed out, redirect to login page
const [firebaseUser, firebaseUserLoading] = useFirebaseUser()
Expand All @@ -43,7 +45,12 @@ const withAdmin = (WrappedComponent) => {
if (!user.isAdmin) {
return (
<div className="text-white dark:text-white">
403 Forbidden: You have no permission to this page.
403{' '}
{t(
'Forbidden: You have no permission to this page',
'Forbidden: You have no permission to this page'
)}
.
</div>
)
}
Expand Down
4 changes: 2 additions & 2 deletions components/common/LanguageSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export default function LanguageSwitcher({
{nameInThatLanguage}
{langCode === 'ar' && (
<span className="ml-1 text-xs text-gray-500">
(Beta)
({t('Beta', 'Beta')})
</span>
)}
</span>
Expand All @@ -128,7 +128,7 @@ export default function LanguageSwitcher({
{nameInThatLanguage}
{langCode === 'ar' && (
<span className="ml-1 text-xs text-gray-500">
(Beta)
({t('Beta', 'Beta')})
</span>
)}
</span>
Expand Down
4 changes: 3 additions & 1 deletion components/nodes/NodeVersionDeleteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export const NodeVersionDeleteModal: React.FC<NodeVersionDeleteModalProps> = ({
>
<Modal.Body className="!bg-gray-800 p-8 md:px-9 md:py-8 rounded-none">
<Modal.Header className="!bg-gray-800 px-8">
<p className="text-white">Delete Version</p>
<p className="text-white">
{t('Delete_Version', 'Delete Version')}
</p>
</Modal.Header>
<div className="space-y-6">
<p className="text-white">
Expand Down
2 changes: 1 addition & 1 deletion components/publisher/PublisherDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const PublisherDetail: React.FC<PublisherDetailProps> = ({ publisher }) => {
if (publisher === undefined || publisher.id === undefined) {
return (
<div className="container p-6 mx-auto h-[90vh] text-white">
Not Found
{t('Not_Found', 'Not Found')}
</div>
)
}
Expand Down
Loading