@tanstack/cta-framework-react-cra 0.44.1 → 0.44.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  import { createFileRoute, useRouter } from '@tanstack/react-router'
2
2
  import { createServerFn } from '@tanstack/react-start'
3
- import { db } from '@/db'
3
+ import { db } from '@/db/index'
4
4
  import { desc } from 'drizzle-orm'
5
5
  import { todos } from '@/db/schema'
6
6
 
@@ -0,0 +1,7 @@
1
+ # Paraglide i18n
2
+
3
+ This add-on wires up ParaglideJS for localized routing and message formatting.
4
+
5
+ - Messages live in `project.inlang/messages`.
6
+ - URLs are localized through the Paraglide Vite plugin and router `rewrite` hooks.
7
+ - Run the dev server or build to regenerate the `src/paraglide` outputs.
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://inlang.com/schema/inlang-message-format",
3
+ "home_page": "Startseite",
4
+ "about_page": "Über uns",
5
+ "example_message": "Willkommen in deiner i18n-App.",
6
+ "language_label": "Sprache",
7
+ "current_locale": "Aktuelle Sprache: {locale}",
8
+ "learn_router": "Paraglide JS lernen"
9
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "$schema": "https://inlang.com/schema/inlang-message-format",
3
+ "home_page": "Home page",
4
+ "about_page": "About page",
5
+ "example_message": "Welcome to your i18n app.",
6
+ "language_label": "Language",
7
+ "current_locale": "Current locale: {locale}",
8
+ "learn_router": "Learn Paraglide JS"
9
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "$schema": "https://inlang.com/schema/project-settings",
3
+ "baseLocale": "en",
4
+ "locales": ["en", "de"],
5
+ "modules": [
6
+ "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js",
7
+ "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js"
8
+ ],
9
+ "plugin.inlang.messageFormat": {
10
+ "pathPattern": "./messages/{locale}.json"
11
+ }
12
+ }
@@ -0,0 +1,44 @@
1
+ // Locale switcher refs:
2
+ // - Paraglide docs: https://inlang.com/m/gerre34r/library-inlang-paraglideJs
3
+ // - Router example: https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide#switching-locale
4
+ import { getLocale, locales, setLocale } from '@/paraglide/runtime'
5
+ import { m } from '@/paraglide/messages'
6
+
7
+ export default function ParaglideLocaleSwitcher() {
8
+ const currentLocale = getLocale()
9
+
10
+ return (
11
+ <div
12
+ style={{
13
+ display: 'flex',
14
+ gap: '0.5rem',
15
+ alignItems: 'center',
16
+ color: 'inherit',
17
+ }}
18
+ aria-label={m.language_label()}
19
+ >
20
+ <span style={{ opacity: 0.85 }}>{m.current_locale({ locale: currentLocale })}</span>
21
+ <div style={{ display: 'flex', gap: '0.25rem' }}>
22
+ {locales.map((locale) => (
23
+ <button
24
+ key={locale}
25
+ onClick={() => setLocale(locale)}
26
+ aria-pressed={locale === currentLocale}
27
+ style={{
28
+ cursor: 'pointer',
29
+ padding: '0.35rem 0.75rem',
30
+ borderRadius: '999px',
31
+ border: '1px solid #d1d5db',
32
+ background: locale === currentLocale ? '#0f172a' : 'transparent',
33
+ color: locale === currentLocale ? '#f8fafc' : 'inherit',
34
+ fontWeight: locale === currentLocale ? 700 : 500,
35
+ letterSpacing: '0.01em',
36
+ }}
37
+ >
38
+ {locale.toUpperCase()}
39
+ </button>
40
+ ))}
41
+ </div>
42
+ </div>
43
+ )
44
+ }
@@ -0,0 +1,34 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import logo from "../logo.svg";
3
+ import { m } from "@/paraglide/messages";
4
+ import LocaleSwitcher from "../components/LocaleSwitcher";
5
+
6
+ export const Route = createFileRoute("/demo/i18n")({
7
+ component: App,
8
+ });
9
+
10
+ function App() {
11
+ return (
12
+ <div className="text-center">
13
+ <header className="min-h-screen flex flex-col items-center justify-center bg-[#282c34] text-white text-[calc(10px+2vmin)] gap-4">
14
+ <img
15
+ src={logo}
16
+ className="h-[40vmin] pointer-events-none animate-[spin_20s_linear_infinite]"
17
+ alt="logo"
18
+ />
19
+ <p>{m.example_message({ username: "TanStack Router" })}</p>
20
+ <a
21
+ className="text-[#61dafb] hover:underline"
22
+ href="https://inlang.com/m/gerre34r/library-inlang-paraglideJs"
23
+ target="_blank"
24
+ rel="noopener noreferrer"
25
+ >
26
+ {m.learn_router()}
27
+ </a>
28
+ <div className="mt-3">
29
+ <LocaleSwitcher />
30
+ </div>
31
+ </header>
32
+ </div>
33
+ );
34
+ }
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "Paraglide (i18n)",
3
+ "description": "i18n with localized routing",
4
+ "phase": "add-on",
5
+ "modes": ["file-router"],
6
+ "type": "add-on",
7
+ "priority": 30,
8
+ "link": "https://github.com/paraglidejs/paraglide-js",
9
+ "routes": [
10
+ {
11
+ "icon": "Languages",
12
+ "url": "/demo/i18n",
13
+ "name": "I18n example",
14
+ "path": "src/routes/demo.i18n.tsx",
15
+ "jsName": "I18nDemo"
16
+ }
17
+ ],
18
+ "integrations": [
19
+ {
20
+ "type": "header-user",
21
+ "path": "src/components/LocaleSwitcher.tsx",
22
+ "jsName": "ParaglideLocaleSwitcher"
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "devDependencies": {
3
+ "@inlang/paraglide-js": "^2.8.0"
4
+ }
5
+ }
@@ -0,0 +1,4 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="Paraglide">
2
+ <rect width="64" height="64" rx="14" fill="#0f172a"/>
3
+ <text x="50%" y="55%" text-anchor="middle" dominant-baseline="central" font-size="36">🪂</text>
4
+ </svg>
@@ -11,6 +11,8 @@ import { HttpLink } from "@apollo/client";
11
11
  <% } %>
12
12
  <% if (addOnEnabled.sentry) { %>
13
13
  import * as Sentry from "@sentry/tanstackstart-react";
14
+ <% } %><% if (addOnEnabled.paraglide) { %>
15
+ import { deLocalizeUrl, localizeUrl } from "./paraglide/runtime";
14
16
  <% } %>
15
17
 
16
18
  // Import the generated route tree
@@ -41,6 +43,13 @@ export const getRouter = () => {
41
43
  ...rqContext,
42
44
  <% } %>
43
45
  },
46
+ <% if (addOnEnabled.paraglide) { %>
47
+ // Paraglide URL rewrite docs: https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide#rewrite-url
48
+ rewrite: {
49
+ input: ({ url }) => deLocalizeUrl(url),
50
+ output: ({ url }) => localizeUrl(url),
51
+ },
52
+ <% } %>
44
53
  <% if (addOnEnabled['tanstack-query'] || addOnEnabled['apollo-client']) { %>
45
54
  defaultPreload: "intent",
46
55
  <% } else { %>
@@ -0,0 +1,9 @@
1
+ <% if (!addOnEnabled.paraglide) { ignoreFile() } %>import { paraglideMiddleware } from './paraglide/server'
2
+ import handler from '@tanstack/react-start/server-entry'
3
+
4
+ // Server-side URL localization/redirects for Paraglide
5
+ export default {
6
+ fetch(req: Request): Promise<Response> {
7
+ return paraglideMiddleware(req, () => handler.fetch(req))
8
+ },
9
+ }
@@ -1,5 +1,8 @@
1
1
  import { defineConfig } from 'vite'
2
2
  import { devtools } from '@tanstack/devtools-vite'
3
+ <% if (addOnEnabled.paraglide) { -%>
4
+ import { paraglideVitePlugin } from "@inlang/paraglide-js"
5
+ <% } -%>
3
6
  import { tanstackStart } from '@tanstack/react-start/plugin/vite';
4
7
  import viteReact from '@vitejs/plugin-react'
5
8
  import viteTsConfigPaths from 'vite-tsconfig-paths'<% if (tailwind) { %>
@@ -8,7 +11,11 @@ import tailwindcss from "@tailwindcss/vite"
8
11
  <% } %>
9
12
 
10
13
  const config = defineConfig({
11
- plugins: [devtools(), <% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportCode(integration) %>,<% } %>
14
+ plugins: [devtools(), <% if (addOnEnabled.paraglide) { %>paraglideVitePlugin({
15
+ project: './project.inlang',
16
+ outdir: './src/paraglide',
17
+ strategy: ['url'],
18
+ }), <% } %><% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportCode(integration) %>,<% } %>
12
19
  // this is the plugin that enables path aliases
13
20
  viteTsConfigPaths({
14
21
  projects: ['./tsconfig.json'],
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "dependencies": {
3
- "nitro": "latest"
3
+ "nitro": "npm:nitro-nightly@latest"
4
4
  }
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/cta-framework-react-cra",
3
- "version": "0.44.1",
3
+ "version": "0.44.2",
4
4
  "description": "CTA Framework for React (Create React App)",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -23,7 +23,7 @@
23
23
  "author": "Jack Herrington <jherr@pobox.com>",
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "@tanstack/cta-engine": "0.44.1"
26
+ "@tanstack/cta-engine": "0.44.2"
27
27
  },
28
28
  "devDependencies": {
29
29
  "@types/node": "^24.6.0",
@@ -105,6 +105,8 @@ import ReactDOM from "react-dom/client";
105
105
  import { RouterProvider, createRouter } from "@tanstack/react-router";
106
106
  <% for(const integration of integrations.filter(i => i.type === 'root-provider')) { %>
107
107
  import * as <%= integration.jsName %> from "<%= relativePath(integration.path) %>";
108
+ <% } %><% if (addOnEnabled.paraglide) { %>
109
+ import { deLocalizeUrl, localizeUrl } from "./paraglide/runtime";
108
110
  <% } %>
109
111
 
110
112
  // Import the generated route tree
@@ -122,7 +124,12 @@ const <%= integration.jsName %>Context = <%= integration.jsName %>.getContext();
122
124
  <% for(const integration of integrations.filter(i => i.type === 'root-provider')) { %>
123
125
  ...<%= integration.jsName %>Context,
124
126
  <% } %>
125
- },
127
+ },<% if (addOnEnabled.paraglide) { %>
128
+ // Paraglide URL rewrite docs: https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide#rewrite-url
129
+ rewrite: {
130
+ input: ({ url }) => deLocalizeUrl(url),
131
+ output: ({ url }) => localizeUrl(url),
132
+ },<% } %>
126
133
  defaultPreload: "intent",
127
134
  scrollRestoration: true,
128
135
  defaultStructuralSharing: true,
@@ -156,4 +163,4 @@ if (rootElement && !rootElement.innerHTML) {
156
163
  // If you want to start measuring performance in your app, pass a function
157
164
  // to log results (for example: reportWebVitals(console.log))
158
165
  // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
159
- reportWebVitals();<% } %>
166
+ reportWebVitals();<% } %>
@@ -1,12 +1,14 @@
1
1
  <% let hasContext = addOnEnabled["apollo-client"] || addOnEnabled["tanstack-query"]; %>
2
2
  <% if (!fileRouter) { ignoreFile() } %>import { <% if (addOnEnabled.start) { %>
3
- HeadContent<% } else { %>Outlet<% } %><% if (addOnEnabled.start) { %>, Scripts<% } %>, <% if (hasContext) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %> } from '@tanstack/react-router'
3
+ HeadContent<% } else { %>Outlet<% } %><% if (addOnEnabled.start) { %>, Scripts<% } %>, <% if (hasContext) { %>createRootRouteWithContext<% } else { %>createRootRoute<% } %><% if (addOnEnabled.paraglide) { %>, redirect<% } %> } from '@tanstack/react-router'
4
4
  import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools';
5
5
  import { TanStackDevtools } from '@tanstack/react-devtools'
6
6
  <% if (addOns.length) { %>
7
7
  import Header from '../components/Header'
8
8
  <% } %><% for(const integration of integrations.filter(i => i.type === 'layout' || i.type === 'provider' || i.type === 'devtools')) { %>
9
9
  import <%= integration.jsName %> from '<%= relativePath(integration.path, true) %>'
10
+ <% } %><% if (addOnEnabled.paraglide) { %>
11
+ import { getLocale, shouldRedirect } from '@/paraglide/runtime'
10
12
  <% } %>
11
13
  <% if (addOnEnabled.start) { %>
12
14
  import appCss from '../styles.css?url'
@@ -32,6 +34,25 @@ interface MyRouterContext <% if (addOnEnabled["apollo-client"]) {%> extends Apol
32
34
  }<% } %>
33
35
 
34
36
  export const Route = <% if (hasContext) { %>createRootRouteWithContext<MyRouterContext>()<% } else { %>createRootRoute<% } %>({
37
+ <% if (addOnEnabled.paraglide) { %>
38
+ beforeLoad: async () => {
39
+ // Other redirect strategies are possible; see
40
+ // https://github.com/TanStack/router/tree/main/examples/react/i18n-paraglide#offline-redirect
41
+ if (typeof document !== 'undefined') {
42
+ document.documentElement.setAttribute('lang', getLocale())
43
+ }
44
+
45
+ <% if (!addOnEnabled.start) { %>// Client-side fallback redirect for SPA/file-router builds. Start apps should
46
+ // prefer server-side paraglideMiddleware (see start template server.ts).
47
+ if (typeof window !== 'undefined') {
48
+ const decision = await shouldRedirect({ url: window.location.href })
49
+
50
+ if (decision.redirectUrl) {
51
+ throw redirect({ href: decision.redirectUrl.href })
52
+ }
53
+ }<% } %>
54
+ },
55
+ <% } %>
35
56
  <% if (addOnEnabled.start) { %>
36
57
  head: () => ({
37
58
  meta: [
@@ -84,7 +105,7 @@ export const Route = <% if (hasContext) { %>createRootRouteWithContext<MyRouterC
84
105
  <% if (addOnEnabled.start) { %>
85
106
  function RootDocument({ children }: { children: React.ReactNode }) {
86
107
  return (
87
- <html lang="en">
108
+ <% if (addOnEnabled.paraglide) { %><html lang={getLocale()}><% } else { %><html lang="en"><% } %>
88
109
  <head>
89
110
  <HeadContent />
90
111
  </head>
@@ -10,7 +10,8 @@
10
10
 
11
11
  /* Bundler mode */
12
12
  "moduleResolution": "bundler",
13
- "allowImportingTsExtensions": true,
13
+ "allowImportingTsExtensions": true,<% if (addOnEnabled.paraglide) { %>
14
+ "allowJs": true,<% } %>
14
15
  "verbatimModuleSyntax": <%= addOnEnabled['start'] ? 'false' : 'true' %>,
15
16
  "noEmit": true,
16
17
 
@@ -1,5 +1,6 @@
1
1
  <% if (addOnEnabled.start) { ignoreFile() } %>import { defineConfig } from "vite";
2
- import { devtools } from '@tanstack/devtools-vite'
2
+ import { devtools } from '@tanstack/devtools-vite'<% if (addOnEnabled.paraglide) { %>
3
+ import { paraglideVitePlugin } from "@inlang/paraglide-js"<% } %>
3
4
  import viteReact from "@vitejs/plugin-react";<% if (tailwind) { %>
4
5
  import tailwindcss from "@tailwindcss/vite";
5
6
  <% } %><%if (fileRouter) { %>
@@ -11,7 +12,11 @@ import federationConfig from "./module-federation.config.js";<% } %><% for(const
11
12
 
12
13
  // https://vitejs.dev/config/
13
14
  export default defineConfig({
14
- plugins: [devtools(), <% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportCode(integration) %>,<% } %> <% if(fileRouter) { %>tanstackRouter({
15
+ plugins: [devtools(), <% if (addOnEnabled.paraglide) { %>paraglideVitePlugin({
16
+ project: './project.inlang',
17
+ outdir: './src/paraglide',
18
+ strategy: ['url'],
19
+ }), <% } %><% for(const integration of integrations.filter(i => i.type === 'vite-plugin')) { %><%- integrationImportCode(integration) %>,<% } %> <% if(fileRouter) { %>tanstackRouter({
15
20
  target: "react",
16
21
  autoCodeSplitting: true,
17
22
  }), <% } %>viteReact(<% if (addOnEnabled.compiler) { %>{