next-intl 4.14.1 β 4.14.3
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.
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ Internationalization (i18n) is an essential part of the user experience, therefo
|
|
|
24
24
|
- π **Next.js-native and performance-obsessed**: App Router, Server Components, static renderingβpick the right tool for the right job, next-intl works everywhere.
|
|
25
25
|
- π **Internationalized routing**: Provide unique pathnames per language and optionally localize pathnames for search engine optimization.
|
|
26
26
|
|
|
27
|
+
[β Read the docs](https://next-intl.dev)
|
|
28
|
+
|
|
27
29
|
## What does it look like?
|
|
28
30
|
|
|
29
31
|
```jsx
|
|
@@ -58,7 +60,35 @@ export default function UserProfile({user}) {
|
|
|
58
60
|
}
|
|
59
61
|
```
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
## Lint your messages
|
|
64
|
+
|
|
65
|
+
As an app grows, messages may drift and become inconsistent.
|
|
66
|
+
|
|
67
|
+
A companion tool, [`eloqnt/cli`](https://cli.eloqnt.dev/docs), catches this by analyzing your source code and messages statically:
|
|
68
|
+
|
|
69
|
+
```console
|
|
70
|
+
$ eloqnt lint
|
|
71
|
+
|
|
72
|
+
messages/de.json
|
|
73
|
+
β
|
|
74
|
+
β "UserProfile.title": "Dein Profil"
|
|
75
|
+
β ββ¬ββββββββββ
|
|
76
|
+
β β°β Inconsistent ICU arguments: missing {firstName} (inconsistent-args)
|
|
77
|
+
β
|
|
78
|
+
β "UserProfile.membership": "Member since {memberSince, date, short}"
|
|
79
|
+
β ββ¬ββββββββββββββββββββββ
|
|
80
|
+
β β°β Missing translation for de (missing-translation)
|
|
81
|
+
|
|
82
|
+
β 1 error
|
|
83
|
+
! 1 warning
|
|
84
|
+
|
|
85
|
+
β Rule details: https://cli.eloqnt.dev/docs/lint-rules/<rule>
|
|
86
|
+
β Run `eloqnt translate` to fill in 1 missing translation
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
It can optionally also fill in missing translations with [`eloqnt translate`](https://cli.eloqnt.dev/docs/cli/translate), using your source code as context.
|
|
90
|
+
|
|
91
|
+
---
|
|
62
92
|
|
|
63
93
|
<div align="center">
|
|
64
94
|
<a href="https://next-intl.dev/redirect?href=https://crowdin.com" target="_blank">
|
|
@@ -139,7 +139,7 @@ function formatPathnameTemplate(template, params) {
|
|
|
139
139
|
template = template.replace(/\[\[/g, '[').replace(/\]\]/g, ']');
|
|
140
140
|
let result = template;
|
|
141
141
|
Object.entries(params).forEach(([key, value]) => {
|
|
142
|
-
result = result.replace(`[${key}]`, value);
|
|
142
|
+
result = result.replace(`[${key}]`, () => value);
|
|
143
143
|
});
|
|
144
144
|
return result;
|
|
145
145
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{normalizeTrailingSlash as e,getSortedPathnames as t,matchesPathname as n,prefixPathname as r,getLocalePrefix as o,templateToRegex as c,getLocalizedTemplate as i}from"../shared/utils.js";function s(e,r,o){const c=t(Object.keys(e));for(const t of c){const c=e[t];if("string"==typeof c){if(n(c,r))return[void 0,t]}else{const s=Object.entries(c),f=s.findIndex((([e])=>e===o));f>0&&s.unshift(s.splice(f,1)[0]);for(const[o]of s){const c=i(e[t],o,t);if(n(c,r))return[o,t]}}}for(const t of Object.keys(e))if(n(t,r))return[void 0,t];return[void 0,void 0]}function f(t,n,r,o){let c="";return c+=p(r,d(n,t)),c=e(c),c}function l(t,n,r){t.endsWith("/")||(t+="/");const o=u(n,r),c=new RegExp(`^(${o.map((([,e])=>e.replaceAll("/","\\/"))).join("|")})/(.*)`,"i"),i=t.match(c);let s=i?"/"+i[2]:t;return"/"!==s&&(s=e(s)),s}function u(e,t,n=!0){const r=e.map((e=>[e,o(e,t)]));return n&&r.sort(((e,t)=>t[1].length-e[1].length)),r}function a(e,t,n,r){const o=u(t,n);r&&o.sort((([e],[t])=>{if(e===r.defaultLocale)return-1;if(t===r.defaultLocale)return 1;const n=r.locales.includes(e),o=r.locales.includes(t);return n&&!o?-1:!n&&o?1:0}));for(const[t,n]of o){let r,o;if(e===n||e.startsWith(n+"/"))r=o=!0;else{const t=e.toLowerCase(),c=n.toLowerCase();(t===c||t.startsWith(c+"/"))&&(r=!1,o=!0)}if(o)return{locale:t,prefix:n,matchedPrefix:e.slice(0,n.length),exact:r}}}function d(t,n){const r=e(n),o=e(t),i=c(o).exec(r);if(!i)return;const s={},f=o.match(/\[([^\]]+)\]/g)??[];for(let e=1;e<i.length;e++){const t=f[e-1];if(!t)continue;const n=t.replace(/[[\]]/g,""),r=i[e]??"";s[n]=r}return s}function p(e,t){if(!t)return e;let n=e=e.replace(/\[\[/g,"[").replace(/\]\]/g,"]");return Object.entries(t).forEach((([e,t])=>{n=n.replace(`[${e}]`,t)})),n}function g(e,t,n){let o=e;return t&&(o=r(t,o)),n&&(o+=n),o}function h(e){return e.get("x-forwarded-host")??e.get("host")??void 0}function x(e,t){return t.defaultLocale===e||t.locales.includes(e)}function m(e,t,n){let r;return e&&x(t,e)&&(r=e),r||(r=n.find((e=>e.defaultLocale===t))),r||(r=n.find((e=>e.locales.includes(t)))),r}function j(t,n){return e(n+t)}function L(e){return`/${e}`}function v(e){return e.replace(/\\/g,"%5C").replace(/[\t\n\r]/g,"").replace(/\/+/g,"/")}export{j as applyBasePath,g as formatPathname,p as formatPathnameTemplate,f as formatTemplatePathname,m as getBestMatchingDomain,h as getHost,s as getInternalTemplate,L as getLocaleAsPrefix,u as getLocalePrefixes,l as getNormalizedPathname,a as getPathnameMatch,d as getRouteParams,x as isLocaleSupportedOnDomain,v as sanitizePathname};
|
|
1
|
+
import{normalizeTrailingSlash as e,getSortedPathnames as t,matchesPathname as n,prefixPathname as r,getLocalePrefix as o,templateToRegex as c,getLocalizedTemplate as i}from"../shared/utils.js";function s(e,r,o){const c=t(Object.keys(e));for(const t of c){const c=e[t];if("string"==typeof c){if(n(c,r))return[void 0,t]}else{const s=Object.entries(c),f=s.findIndex((([e])=>e===o));f>0&&s.unshift(s.splice(f,1)[0]);for(const[o]of s){const c=i(e[t],o,t);if(n(c,r))return[o,t]}}}for(const t of Object.keys(e))if(n(t,r))return[void 0,t];return[void 0,void 0]}function f(t,n,r,o){let c="";return c+=p(r,d(n,t)),c=e(c),c}function l(t,n,r){t.endsWith("/")||(t+="/");const o=u(n,r),c=new RegExp(`^(${o.map((([,e])=>e.replaceAll("/","\\/"))).join("|")})/(.*)`,"i"),i=t.match(c);let s=i?"/"+i[2]:t;return"/"!==s&&(s=e(s)),s}function u(e,t,n=!0){const r=e.map((e=>[e,o(e,t)]));return n&&r.sort(((e,t)=>t[1].length-e[1].length)),r}function a(e,t,n,r){const o=u(t,n);r&&o.sort((([e],[t])=>{if(e===r.defaultLocale)return-1;if(t===r.defaultLocale)return 1;const n=r.locales.includes(e),o=r.locales.includes(t);return n&&!o?-1:!n&&o?1:0}));for(const[t,n]of o){let r,o;if(e===n||e.startsWith(n+"/"))r=o=!0;else{const t=e.toLowerCase(),c=n.toLowerCase();(t===c||t.startsWith(c+"/"))&&(r=!1,o=!0)}if(o)return{locale:t,prefix:n,matchedPrefix:e.slice(0,n.length),exact:r}}}function d(t,n){const r=e(n),o=e(t),i=c(o).exec(r);if(!i)return;const s={},f=o.match(/\[([^\]]+)\]/g)??[];for(let e=1;e<i.length;e++){const t=f[e-1];if(!t)continue;const n=t.replace(/[[\]]/g,""),r=i[e]??"";s[n]=r}return s}function p(e,t){if(!t)return e;let n=e=e.replace(/\[\[/g,"[").replace(/\]\]/g,"]");return Object.entries(t).forEach((([e,t])=>{n=n.replace(`[${e}]`,(()=>t))})),n}function g(e,t,n){let o=e;return t&&(o=r(t,o)),n&&(o+=n),o}function h(e){return e.get("x-forwarded-host")??e.get("host")??void 0}function x(e,t){return t.defaultLocale===e||t.locales.includes(e)}function m(e,t,n){let r;return e&&x(t,e)&&(r=e),r||(r=n.find((e=>e.defaultLocale===t))),r||(r=n.find((e=>e.locales.includes(t)))),r}function j(t,n){return e(n+t)}function L(e){return`/${e}`}function v(e){return e.replace(/\\/g,"%5C").replace(/[\t\n\r]/g,"").replace(/\/+/g,"/")}export{j as applyBasePath,g as formatPathname,p as formatPathnameTemplate,f as formatTemplatePathname,m as getBestMatchingDomain,h as getHost,s as getInternalTemplate,L as getLocaleAsPrefix,u as getLocalePrefixes,l as getNormalizedPathname,a as getPathnameMatch,d as getRouteParams,x as isLocaleSupportedOnDomain,v as sanitizePathname};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getSortedPathnames as e,matchesPathname as n,isLocalizableHref as t,prefixPathname as r,normalizeTrailingSlash as o,getLocalizedTemplate as a,getLocalePrefix as i}from"../../shared/utils.js";function c(e){return"string"==typeof e?{pathname:e}:e}function s(e){function n(e){return String(e)}const t=new URLSearchParams;for(const[r,o]of Object.entries(e))Array.isArray(o)?o.forEach((e=>{t.append(r,n(e))})):t.set(r,n(o));return"?"+t.toString()}function f({pathname:e,locale:n,params:t,pathnames:r,query:i}){function c(e){const c=r[e];let f;if(c){const r=a(c,n,e);f=r,t&&Object.entries(t).forEach((([e,n])=>{let t,r;Array.isArray(n)?(t=`(\\[)?\\[...${e}\\](\\])?`,r=n.map((e=>String(e))).join("/")):(t=`\\[${e}\\]`,r=String(n)),f=f.replace(new RegExp(t,"g"),r)})),f=f.replace(/\[\[\.\.\..+\]\]/g,""),f=function(e){return new URL(e,"http://l").pathname}(f)}else f=e;return f=o(f),i&&(f+=s(i)),f}if("string"==typeof e)return c(e);{const{pathname:n,...t}=e;return{...t,pathname:c(n)}}}function l(t,r,o){const i=e(Object.keys(o)),c=decodeURI(r);for(const e of i){const r=o[e];if("string"==typeof r){if(n(r,c))return e}else if(n(a(r,t,e),c))return e}return r}function u(e,n=window.location.pathname){return"/"===e?n:n.replace(e,"")}function p(e,n,o,a){const{mode:c}=o.localePrefix;let s;if(void 0!==a)s=a;else if(t(e)){const e=o.domains?.find((e=>e.locales.includes(n))),t=e?.localePrefix||c;"always"===t?s=!0:"as-needed"===t&&(s=e?n!==e.defaultLocale:n!==o.defaultLocale)}return s?r(i(n,o.localePrefix),e):e}export{p as applyPathnamePrefix,f as compileLocalizedPathname,u as getBasePath,l as getRoute,c as normalizeNameOrNameWithParams,s as serializeSearchParams};
|
|
1
|
+
import{getSortedPathnames as e,matchesPathname as n,isLocalizableHref as t,prefixPathname as r,normalizeTrailingSlash as o,getLocalizedTemplate as a,getLocalePrefix as i}from"../../shared/utils.js";function c(e){return"string"==typeof e?{pathname:e}:e}function s(e){function n(e){return String(e)}const t=new URLSearchParams;for(const[r,o]of Object.entries(e))Array.isArray(o)?o.forEach((e=>{t.append(r,n(e))})):t.set(r,n(o));return"?"+t.toString()}function f({pathname:e,locale:n,params:t,pathnames:r,query:i}){function c(e){const c=r[e];let f;if(c){const r=a(c,n,e);f=r,t&&Object.entries(t).forEach((([e,n])=>{let t,r;Array.isArray(n)?(t=`(\\[)?\\[...${e}\\](\\])?`,r=n.map((e=>String(e))).join("/")):(t=`\\[${e}\\]`,r=String(n)),f=f.replace(new RegExp(t,"g"),(()=>r))})),f=f.replace(/\[\[\.\.\..+\]\]/g,""),f=function(e){return new URL(e,"http://l").pathname}(f)}else f=e;return f=o(f),i&&(f+=s(i)),f}if("string"==typeof e)return c(e);{const{pathname:n,...t}=e;return{...t,pathname:c(n)}}}function l(t,r,o){const i=e(Object.keys(o)),c=decodeURI(r);for(const e of i){const r=o[e];if("string"==typeof r){if(n(r,c))return e}else if(n(a(r,t,e),c))return e}return r}function u(e,n=window.location.pathname){return"/"===e?n:n.replace(e,"")}function p(e,n,o,a){const{mode:c}=o.localePrefix;let s;if(void 0!==a)s=a;else if(t(e)){const e=o.domains?.find((e=>e.locales.includes(n))),t=e?.localePrefix||c;"always"===t?s=!0:"as-needed"===t&&(s=e?n!==e.defaultLocale:n!==o.defaultLocale)}return s?r(i(n,o.localePrefix),e):e}export{p as applyPathnamePrefix,f as compileLocalizedPathname,u as getBasePath,l as getRoute,c as normalizeNameOrNameWithParams,s as serializeSearchParams};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "next-intl",
|
|
3
|
-
"version": "4.14.
|
|
3
|
+
"version": "4.14.3",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"author": "Jan Amann <jan@amann.work>",
|
|
6
6
|
"funding": [
|
|
@@ -124,20 +124,20 @@
|
|
|
124
124
|
"next.js"
|
|
125
125
|
],
|
|
126
126
|
"dependencies": {
|
|
127
|
-
"@eloqnt/config": "^0.0
|
|
128
|
-
"@eloqnt/format-json": "^0.0
|
|
129
|
-
"@eloqnt/format-po": "^0.0
|
|
127
|
+
"@eloqnt/config": "^0.1.0",
|
|
128
|
+
"@eloqnt/format-json": "^0.1.0",
|
|
129
|
+
"@eloqnt/format-po": "^0.1.0",
|
|
130
130
|
"@formatjs/intl-localematcher": "^0.8.1",
|
|
131
131
|
"@parcel/watcher": "^2.4.1",
|
|
132
132
|
"@swc/core": "~1.16.0",
|
|
133
|
-
"icu-minify": "^4.14.
|
|
133
|
+
"icu-minify": "^4.14.3",
|
|
134
134
|
"negotiator": "^1.0.0",
|
|
135
|
-
"next-intl-swc-plugin-extractor": "4.14.
|
|
136
|
-
"use-intl": "^4.14.
|
|
135
|
+
"next-intl-swc-plugin-extractor": "4.14.3",
|
|
136
|
+
"use-intl": "^4.14.3"
|
|
137
137
|
},
|
|
138
138
|
"peerDependencies": {
|
|
139
139
|
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
140
140
|
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
|
|
141
141
|
},
|
|
142
|
-
"gitHead": "
|
|
142
|
+
"gitHead": "e9b1637796481a96b15dd081d5b92a5b1fa8ca02"
|
|
143
143
|
}
|