feat: enforce i18n import conventions via ESLint (#8701)

## Summary

Enforce i18n import conventions via ESLint: Vue components must use
`useI18n()`, non-composable `.ts` files must use the global `t` from
`@/i18n`.

## Changes

- **What**: Two new `no-restricted-imports` rules in `eslint.config.ts`
(both `warn` severity for incremental migration). Removed the disabled
`@/i18n--to-enable` placeholder from `.oxlintrc.json`.
- `.vue` files: disallow importing `t`/`d`/`st`/`te` from `@/i18n` (37
existing violations to migrate)
- Non-composable `.ts` files: disallow importing `useI18n` from
`vue-i18n` (2 existing violations)
- Composable `use*.ts`, test files, and `src/i18n.ts` are excluded from
Rule 2

## Review Focus

- The rules are placed after `oxlint.buildFromOxlintConfigFile()` to
re-enable ESLint's `no-restricted-imports` for these specific file
scopes without conflicting with oxlint's base rule (which handles
PrimeVue deprecations).
- `warn` severity chosen so CI is not blocked while existing violations
are migrated.

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8701-feat-enforce-i18n-import-conventions-via-ESLint-2ff6d73d36508123b6f9edf2693fb5e0)
by [Unito](https://www.unito.io)

---------

Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
Alexander Brown
2026-02-06 14:03:00 -08:00
committed by GitHub
parent 0e3314bbd3
commit 5441f70cd5
2 changed files with 41 additions and 5 deletions

View File

@@ -60,11 +60,6 @@
{
"name": "primevue/sidebar",
"message": "Sidebar is deprecated in PrimeVue 4+. Use Drawer instead: import Drawer from 'primevue/drawer'"
},
{
"name": "@/i18n--to-enable",
"importNames": ["st", "t", "te", "d"],
"message": "Don't import `@/i18n` directly, prefer `useI18n()`"
}
]
}

View File

@@ -279,5 +279,46 @@ export default defineConfig([
'import-x/no-duplicates': 'off',
'import-x/consistent-type-specifier-style': 'off'
}
},
// i18n import enforcement
// Vue components must use the useI18n() composable, not the global t/d/st/te
{
files: ['**/*.vue'],
rules: {
'no-restricted-imports': [
'warn',
{
paths: [
{
name: '@/i18n',
importNames: ['t', 'd', 'st', 'te'],
message:
"In Vue components, use `const { t } = useI18n()` instead of importing from '@/i18n'."
}
]
}
]
}
},
// Non-composable .ts files must use the global t/d/st/te, not useI18n()
{
files: ['**/*.ts'],
ignores: ['**/use[A-Z]*.ts', '**/*.test.ts', 'src/i18n.ts'],
rules: {
'no-restricted-imports': [
'warn',
{
paths: [
{
name: 'vue-i18n',
importNames: ['useI18n'],
message:
"useI18n() requires Vue setup context. Use `import { t } from '@/i18n'` instead."
}
]
}
]
}
}
])