hensei-web/next.config.js
Justin Edmund 3d67622353
Fix i18n migration to next-intl (#430)
## Summary
- Fixed translation key format compatibility with next-intl
- Fixed pluralization format from i18next to next-intl format
- Fixed dynamic translation key error handling
- Updated server components to match API response structure
- Fixed useSearchParams import location

## Changes
- Changed pluralization from `{{count}} items` to `{count} items` format
- Added proper error handling for missing translation keys
- Fixed import paths for next-intl hooks
- Fixed PartyPageClient trying to set non-existent appState.parties

## Test plan
- [x] Verified translations render correctly
- [x] Tested pluralization works with different counts
- [x] Confirmed no console errors about missing translations
- [x] Tested party page functionality

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-03 16:25:59 -07:00

121 lines
2.9 KiB
JavaScript

/** @type {import('next').NextConfig} */
const path = require('path')
const createNextIntlPlugin = require('next-intl/plugin')
const withNextIntl = createNextIntlPlugin('./i18n/request.ts')
const nextConfig = {
reactStrictMode: true,
sassOptions: {
prependData: '@import "variables";',
includePaths: [path.join(__dirname, 'styles')],
},
async rewrites() {
return [
{
source: '/',
destination: '/new',
},
{
source: '/characters',
destination: '/new',
},
{
source: '/summons',
destination: '/new',
},
{
source: '/weapons',
destination: '/new',
},
{
source: '/updates',
destination: '/about',
},
{
source: '/roadmap',
destination: '/about',
},
{
source: '/p/:shortcode/preview',
destination: '/api/preview/:shortcode',
},
{
source: '/p/:shortcode/characters',
destination: '/p/:shortcode',
},
{
source: '/p/:shortcode/weapons',
destination: '/p/:shortcode',
},
{
source: '/p/:shortcode/summons',
destination: '/p/:shortcode',
},
{
source: '/p/:shortcode/:garbage',
destination: '/p/:shortcode',
},
]
},
async redirects() {
return [
{
source: '/transfer/version',
destination:
'https://raw.githubusercontent.com/Vazkii/hensei-transfer/main/version',
permanent: true,
},
]
},
webpack(config) {
// Set up alias for styles
config.resolve.alias = {
...config.resolve.alias,
'@styles': path.resolve(__dirname, 'styles'),
}
// Set up rules for SVG files
const fileLoaderRule = config.module.rules.find((rule) =>
rule.test?.test?.('.svg'),
)
if (fileLoaderRule) {
config.module.rules.push(
// Reapply the existing rule, but only for svg imports ending in ?url
{
...fileLoaderRule,
test: /\.svg$/i,
resourceQuery: /url/, // *.svg?url
},
// Convert all other *.svg imports to React components
{
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
resourceQuery: { not: /url/ }, // exclude if *.svg?url
use: ['@svgr/webpack'],
},
)
// Modify the file loader rule to ignore *.svg, since we have it handled now.
fileLoaderRule.exclude = /\.svg$/i
} else {
// If no file loader rule exists, just add our SVG handler
config.module.rules.push({
test: /\.svg$/i,
issuer: /\.[jt]sx?$/,
use: ['@svgr/webpack'],
})
}
// Disable CSS modules
// config.module.rules[2].oneOf.forEach((one) => {
// if (!`${one.issuer?.and}`.includes('_app')) return
// one.issuer.and = [path.resolve(__dirname)]
// })
return config
},
}
module.exports = withNextIntl(nextConfig)