Fix: Can'

Error message:
You can'
Internationalization 2025-01-25

What Causes This Error?

This error occurs when you use an i18n utility function that isn’t compatible with your configured routing strategy. Different routing strategies (pathname prefix, domains, manual) support different functions.

The Problem

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    routing: 'manual',  // Manual routing
  },
});
---
// ❌ These functions require non-manual routing
import { getRelativeLocaleUrl } from 'astro:i18n';
const url = getRelativeLocaleUrl('es', '/about');
---

The Fix

Match Functions to Strategy

// For automatic routing (default)
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    // routing: 'pathname-prefix-always' (or no routing key)
  },
});
---
// ✅ These work with automatic routing
import {
  getRelativeLocaleUrl,
  getAbsoluteLocaleUrl,
  getRelativeLocaleUrlList,
  getAbsoluteLocaleUrlList,
} from 'astro:i18n';

const url = getRelativeLocaleUrl('es', '/about');
---

Common Scenarios

Pathname Prefix Strategy

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es', 'fr'],
    routing: {
      prefixDefaultLocale: false,  // /about vs /es/about
    },
  },
});
---
// ✅ All URL functions available
import { getRelativeLocaleUrl } from 'astro:i18n';

const aboutEn = getRelativeLocaleUrl('en', '/about');  // /about
const aboutEs = getRelativeLocaleUrl('es', '/about');  // /es/about
---

Manual Routing Strategy

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    routing: 'manual',  // You handle all routing
  },
});
---
// With manual routing, build URLs yourself
const locale = Astro.currentLocale || 'en';
const aboutUrl = locale === 'en' ? '/about' : `/${locale}/about`;
---

Domains Strategy

// astro.config.mjs
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    domains: {
      en: 'https://example.com',
      es: 'https://es.example.com',
    },
  },
});
---
// ✅ Use absolute URLs with domains
import { getAbsoluteLocaleUrl } from 'astro:i18n';

const aboutEs = getAbsoluteLocaleUrl('es', '/about');
// Returns: https://es.example.com/about
---

Available Functions by Strategy

FunctionPathnameManualDomains
getRelativeLocaleUrl⚠️
getAbsoluteLocaleUrl
getRelativeLocaleUrlList⚠️
getAbsoluteLocaleUrlList
getPathByLocale
getLocaleByPath

Manual Routing with Middleware

// src/middleware.ts
import { defineMiddleware } from 'astro:middleware';

export const onRequest = defineMiddleware((context, next) => {
  // Manual locale detection
  const locale = context.url.pathname.split('/')[1];
  const validLocales = ['en', 'es', 'fr'];

  if (validLocales.includes(locale)) {
    context.locals.locale = locale;
  } else {
    context.locals.locale = 'en';
  }

  return next();
});

Custom URL Helper for Manual Routing

// src/i18n/utils.ts
export function getLocalizedUrl(locale: string, path: string): string {
  if (locale === 'en') {
    return path;  // Default locale without prefix
  }
  return `/${locale}${path}`;
}
---
import { getLocalizedUrl } from '../i18n/utils';

const aboutUrl = getLocalizedUrl('es', '/about');  // /es/about
---

Switching Strategies

// Switch from manual to automatic
export default defineConfig({
  i18n: {
    defaultLocale: 'en',
    locales: ['en', 'es'],
    // Remove 'manual' to enable automatic routing
    routing: {
      prefixDefaultLocale: false,
    },
  },
});

Quick Checklist

  • Check your routing strategy in config
  • Use URL functions only with automatic routing
  • Manual routing requires custom URL building
  • Domains strategy uses absolute URLs
  • Match function usage to strategy type