From e4cfb4c15630a310567a41ccc9f64298b55b491c Mon Sep 17 00:00:00 2001 From: aurambaj Date: Wed, 15 Nov 2023 20:29:45 +0000 Subject: [PATCH] deploy: de6b8344eea75f1a913afed178d544cdca8b2b6a --- 404.html | 4 ++-- .../js/{0a3ea1d4.bdd1efdd.js => 0a3ea1d4.250ffd74.js} | 2 +- .../js/{1e924268.b4cbbcc8.js => 1e924268.82198e31.js} | 2 +- .../js/{2191c1fe.80bda392.js => 2191c1fe.b440b918.js} | 2 +- .../js/{9c79f53b.34cde490.js => 9c79f53b.503fa77e.js} | 2 +- ...ntime~main.c54225cc.js => runtime~main.57631990.js} | 2 +- docs/annotation-processor/index.html | 4 ++-- docs/caching/index.html | 4 ++-- docs/examples/index.html | 4 ++-- docs/fluent-api/index.html | 4 ++-- docs/getting-started/index.html | 4 ++-- docs/icu4j/index.html | 4 ++-- docs/installation/bazel/index.html | 6 +++--- docs/installation/gradle/index.html | 8 ++++---- docs/installation/index.html | 6 +++--- docs/installation/maven/index.html | 10 +++++----- docs/introduction/index.html | 4 ++-- docs/resource-bundle/index.html | 4 ++-- index.html | 4 ++-- 19 files changed, 40 insertions(+), 40 deletions(-) rename assets/js/{0a3ea1d4.bdd1efdd.js => 0a3ea1d4.250ffd74.js} (98%) rename assets/js/{1e924268.b4cbbcc8.js => 1e924268.82198e31.js} (98%) rename assets/js/{2191c1fe.80bda392.js => 2191c1fe.b440b918.js} (97%) rename assets/js/{9c79f53b.34cde490.js => 9c79f53b.503fa77e.js} (95%) rename assets/js/{runtime~main.c54225cc.js => runtime~main.57631990.js} (95%) diff --git a/404.html b/404.html index c10931e..0f9ef9b 100644 --- a/404.html +++ b/404.html @@ -4,13 +4,13 @@ Page Not Found | L10nMessages - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/0a3ea1d4.bdd1efdd.js b/assets/js/0a3ea1d4.250ffd74.js similarity index 98% rename from assets/js/0a3ea1d4.bdd1efdd.js rename to assets/js/0a3ea1d4.250ffd74.js index ad0b983..05ca435 100644 --- a/assets/js/0a3ea1d4.bdd1efdd.js +++ b/assets/js/0a3ea1d4.250ffd74.js @@ -1 +1 @@ -"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[101],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>d});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var o=a.createContext({}),p=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(o.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,s=e.originalType,o=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=p(t),d=r,g=u["".concat(o,".").concat(d)]||u[d]||m[d]||s;return t?a.createElement(g,l(l({ref:n},c),{},{components:t})):a.createElement(g,l({ref:n},c))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var s=t.length,l=new Array(s);l[0]=u;var i={};for(var o in n)hasOwnProperty.call(n,o)&&(i[o]=n[o]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var p=2;p{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>i,toc:()=>p});var a=t(7462),r=(t(7294),t(3905));const s={title:"Bazel"},l=void 0,i={unversionedId:"installation/bazel",id:"installation/bazel",title:"Bazel",description:"For Bazel main steps are:",source:"@site/docs/installation/bazel.md",sourceDirName:"installation",slug:"/installation/bazel",permalink:"/docs/installation/bazel",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/bazel.md",tags:[],version:"current",frontMatter:{title:"Bazel"},sidebar:"docs",previous:{title:"Installation",permalink:"/docs/installation/"},next:{title:"Gradle",permalink:"/docs/installation/gradle"}},o={},p=[{value:"JDK only",id:"jdk-only",level:2},{value:"With ICU4J",id:"with-icu4j",level:2},{value:"External dependencies",id:"external-dependencies",level:2}],c={toc:p};function m(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"For ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel")," main steps are:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Add ",(0,r.kt)("a",{parentName:"li",href:"#external-dependencies"},"external dependencies"),", for example using ",(0,r.kt)("inlineCode",{parentName:"li"},"rules_jvm_external")),(0,r.kt)("li",{parentName:"ul"},"Register ",(0,r.kt)("inlineCode",{parentName:"li"},"properties")," files using a ",(0,r.kt)("inlineCode",{parentName:"li"},"filegroup")),(0,r.kt)("li",{parentName:"ul"},"Configure the annotation processor using a ",(0,r.kt)("inlineCode",{parentName:"li"},"java_plugin")),(0,r.kt)("li",{parentName:"ul"},"Add a Java rule with ",(0,r.kt)("inlineCode",{parentName:"li"},"java_binary")," to build the application")),(0,r.kt)("h2",{id:"jdk-only"},"JDK only"),(0,r.kt)("p",null,"Create a ",(0,r.kt)("inlineCode",{parentName:"p"},"filegroup")," to register the properties files that you wish to use"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'filegroup(\n name="l10nresources",\n srcs=glob(["src/main/resources/**/*.properties"])\n)\n')),(0,r.kt)("p",null,"Use a ",(0,r.kt)("inlineCode",{parentName:"p"},"java_plugin")," to configure the annotation processor that processes the registered properties\nfiles"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'java_plugin(\n name="l10nmessages_proc",\n processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages_proc",\n "@maven//:com_pinterest_l10nmessages_l10nmessages"\n ],\n resources=["l10nresources"]\n)\n')),(0,r.kt)("p",null,"In ",(0,r.kt)("inlineCode",{parentName:"p"},"java_binary"),", add the resources previously define in ",(0,r.kt)("inlineCode",{parentName:"p"},"resources"),", register the annotation\nprocessor in ",(0,r.kt)("inlineCode",{parentName:"p"},"plugins")," and finally add a dependency on the library runtime in ",(0,r.kt)("inlineCode",{parentName:"p"},"deps")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'java_binary(\n name="l10nbazel",\n srcs=glob(["src/main/java/**/*.java"]),\n resources=["l10nresources"],\n plugins=["l10nmessages_proc"],\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages"\n ],\n main_class="com.pinterest.l10nmessages.example.Application",\n)\n')),(0,r.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,r.kt)("p",null,'Same as "JDK only" and add the ',(0,r.kt)("inlineCode",{parentName:"p"},"icu4j")," dependency to both the annotation processor and runtime\ndependencies"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'\nfilegroup(\n name="l10nresources",\n srcs=glob(["src/main/resources/**/*.properties"])\n)\n\njava_plugin(\n name="l10nmessages_proc",\n processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages_proc",\n "@maven//:com_pinterest_l10nmessages_l10nmessages",\n "@maven//:com_ibm_icu_icu4j"\n ],\n resources=["l10nresources"]\n)\n\njava_binary(\n name="l10nbazel",\n srcs=glob(["src/main/java/**/*.java"]),\n resources=["l10nresources"],\n plugins=["l10nmessages_proc"],\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages",\n "@maven//:com_ibm_icu_icu4j"\n ],\n main_class="com.pinterest.l10nmessages.example.Application",\n)\n')),(0,r.kt)("h2",{id:"external-dependencies"},"External dependencies"),(0,r.kt)("p",null,"Use ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/bazelbuild/rules_jvm_external"},"rules_jvm_external")," to fetch external\ndependencies from Maven."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"WORKSPACE",WORKSPACE:!0},'RULES_JVM_EXTERNAL_TAG = "4.2"\nRULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"\n\nhttp_archive(\n name = "rules_jvm_external",\n strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,\n sha256 = RULES_JVM_EXTERNAL_SHA,\n url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,\n)\n\nload("@rules_jvm_external//:defs.bzl", "maven_install")\n\nmaven_install(\n artifacts = [\n "com.ibm.icu:icu4j:72.1"\n "com.pinterest.l10nmessages:l10nmessages:1.0.3"\n "com.pinterest.l10nmessages:l10nmessages-proc:1.0.3"\n ],\n repositories = [\n "https://repo1.maven.org/maven2",\n ],\n)\n')))}m.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[101],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>d});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function l(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var o=a.createContext({}),p=function(e){var n=a.useContext(o),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(o.Provider,{value:n},e.children)},m={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},u=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,s=e.originalType,o=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),u=p(t),d=r,g=u["".concat(o,".").concat(d)]||u[d]||m[d]||s;return t?a.createElement(g,l(l({ref:n},c),{},{components:t})):a.createElement(g,l({ref:n},c))}));function d(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var s=t.length,l=new Array(s);l[0]=u;var i={};for(var o in n)hasOwnProperty.call(n,o)&&(i[o]=n[o]);i.originalType=e,i.mdxType="string"==typeof e?e:r,l[1]=i;for(var p=2;p{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>l,default:()=>m,frontMatter:()=>s,metadata:()=>i,toc:()=>p});var a=t(7462),r=(t(7294),t(3905));const s={title:"Bazel"},l=void 0,i={unversionedId:"installation/bazel",id:"installation/bazel",title:"Bazel",description:"For Bazel main steps are:",source:"@site/docs/installation/bazel.md",sourceDirName:"installation",slug:"/installation/bazel",permalink:"/docs/installation/bazel",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/bazel.md",tags:[],version:"current",frontMatter:{title:"Bazel"},sidebar:"docs",previous:{title:"Installation",permalink:"/docs/installation/"},next:{title:"Gradle",permalink:"/docs/installation/gradle"}},o={},p=[{value:"JDK only",id:"jdk-only",level:2},{value:"With ICU4J",id:"with-icu4j",level:2},{value:"External dependencies",id:"external-dependencies",level:2}],c={toc:p};function m(e){let{components:n,...t}=e;return(0,r.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"For ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel")," main steps are:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Add ",(0,r.kt)("a",{parentName:"li",href:"#external-dependencies"},"external dependencies"),", for example using ",(0,r.kt)("inlineCode",{parentName:"li"},"rules_jvm_external")),(0,r.kt)("li",{parentName:"ul"},"Register ",(0,r.kt)("inlineCode",{parentName:"li"},"properties")," files using a ",(0,r.kt)("inlineCode",{parentName:"li"},"filegroup")),(0,r.kt)("li",{parentName:"ul"},"Configure the annotation processor using a ",(0,r.kt)("inlineCode",{parentName:"li"},"java_plugin")),(0,r.kt)("li",{parentName:"ul"},"Add a Java rule with ",(0,r.kt)("inlineCode",{parentName:"li"},"java_binary")," to build the application")),(0,r.kt)("h2",{id:"jdk-only"},"JDK only"),(0,r.kt)("p",null,"Create a ",(0,r.kt)("inlineCode",{parentName:"p"},"filegroup")," to register the properties files that you wish to use"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'filegroup(\n name="l10nresources",\n srcs=glob(["src/main/resources/**/*.properties"])\n)\n')),(0,r.kt)("p",null,"Use a ",(0,r.kt)("inlineCode",{parentName:"p"},"java_plugin")," to configure the annotation processor that processes the registered properties\nfiles"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'java_plugin(\n name="l10nmessages_proc",\n processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages_proc",\n "@maven//:com_pinterest_l10nmessages_l10nmessages"\n ],\n resources=["l10nresources"]\n)\n')),(0,r.kt)("p",null,"In ",(0,r.kt)("inlineCode",{parentName:"p"},"java_binary"),", add the resources previously define in ",(0,r.kt)("inlineCode",{parentName:"p"},"resources"),", register the annotation\nprocessor in ",(0,r.kt)("inlineCode",{parentName:"p"},"plugins")," and finally add a dependency on the library runtime in ",(0,r.kt)("inlineCode",{parentName:"p"},"deps")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'java_binary(\n name="l10nbazel",\n srcs=glob(["src/main/java/**/*.java"]),\n resources=["l10nresources"],\n plugins=["l10nmessages_proc"],\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages"\n ],\n main_class="com.pinterest.l10nmessages.example.Application",\n)\n')),(0,r.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,r.kt)("p",null,'Same as "JDK only" and add the ',(0,r.kt)("inlineCode",{parentName:"p"},"icu4j")," dependency to both the annotation processor and runtime\ndependencies"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"title=BUILD",title:"BUILD"},'\nfilegroup(\n name="l10nresources",\n srcs=glob(["src/main/resources/**/*.properties"])\n)\n\njava_plugin(\n name="l10nmessages_proc",\n processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages_proc",\n "@maven//:com_pinterest_l10nmessages_l10nmessages",\n "@maven//:com_ibm_icu_icu4j"\n ],\n resources=["l10nresources"]\n)\n\njava_binary(\n name="l10nbazel",\n srcs=glob(["src/main/java/**/*.java"]),\n resources=["l10nresources"],\n plugins=["l10nmessages_proc"],\n deps=[\n "@maven//:com_pinterest_l10nmessages_l10nmessages",\n "@maven//:com_ibm_icu_icu4j"\n ],\n main_class="com.pinterest.l10nmessages.example.Application",\n)\n')),(0,r.kt)("h2",{id:"external-dependencies"},"External dependencies"),(0,r.kt)("p",null,"Use ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/bazelbuild/rules_jvm_external"},"rules_jvm_external")," to fetch external\ndependencies from Maven."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-python",metastring:"WORKSPACE",WORKSPACE:!0},'RULES_JVM_EXTERNAL_TAG = "4.2"\nRULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"\n\nhttp_archive(\n name = "rules_jvm_external",\n strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,\n sha256 = RULES_JVM_EXTERNAL_SHA,\n url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,\n)\n\nload("@rules_jvm_external//:defs.bzl", "maven_install")\n\nmaven_install(\n artifacts = [\n "com.ibm.icu:icu4j:72.1"\n "com.pinterest.l10nmessages:l10nmessages:1.0.4"\n "com.pinterest.l10nmessages:l10nmessages-proc:1.0.4"\n ],\n repositories = [\n "https://repo1.maven.org/maven2",\n ],\n)\n')))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1e924268.b4cbbcc8.js b/assets/js/1e924268.82198e31.js similarity index 98% rename from assets/js/1e924268.b4cbbcc8.js rename to assets/js/1e924268.82198e31.js index 7bb6e9d..0db11fe 100644 --- a/assets/js/1e924268.b4cbbcc8.js +++ b/assets/js/1e924268.82198e31.js @@ -1 +1 @@ -"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[614],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),m=r,f=u["".concat(l,".").concat(m)]||u[m]||d[m]||i;return n?a.createElement(f,o(o({ref:t},c),{},{components:n})):a.createElement(f,o({ref:t},c))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const i={title:"Installation",description:"Java internationalization made easy and safe!"},o=void 0,s={unversionedId:"installation/installation",id:"installation/installation",title:"Installation",description:"Java internationalization made easy and safe!",source:"@site/docs/installation/installation.md",sourceDirName:"installation",slug:"/installation/",permalink:"/docs/installation/",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/installation.md",tags:[],version:"current",frontMatter:{title:"Installation",description:"Java internationalization made easy and safe!"},sidebar:"docs",previous:{title:"Getting Started",permalink:"/docs/getting-started"},next:{title:"Bazel",permalink:"/docs/installation/bazel"}},l={},p=[{value:"Annotation processor",id:"annotation-processor",level:2},{value:"Fluent API",id:"fluent-api",level:2},{value:"Register Properties files",id:"register-properties-files",level:2}],c={toc:p};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Java 8+ supported"),(0,r.kt)("p",{parentName:"admonition"},"Maven group id is ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages")," and artifact id ",(0,r.kt)("inlineCode",{parentName:"p"},"l10nmessages"),". "),(0,r.kt)("p",{parentName:"admonition"},"The latest version is ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0.3"),".")),(0,r.kt)("p",null,"Each build system: ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"Gradle")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Maven")," has a slightly different setup, but the main steps\nare:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Set up the annotation processor"),(0,r.kt)("li",{parentName:"ul"},"Add the runtime library / fluent API"),(0,r.kt)("li",{parentName:"ul"},"Register ",(0,r.kt)("inlineCode",{parentName:"li"},"properties")," files")),(0,r.kt)("p",null,"It is recommended to use the annotation processor together with the runtime library but both can be\nused independently. The documentation covers setting up both together."),(0,r.kt)("h2",{id:"annotation-processor"},"Annotation processor"),(0,r.kt)("p",null,"The annotation processor: ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages.L10nPropertiesProcessor")," is used to generate\nenums for strong typing and to perform compile time checks. It must have access to the properties\nfiles through the annotation path or classpath which is build system dependent."),(0,r.kt)("h2",{id:"fluent-api"},"Fluent API"),(0,r.kt)("p",null,"The fluent API: ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages.L10nMessages")," is used at runtime to load and format\nmessages. Properties files are accessed through the classpath as defined by JDK / ICU resource\nbundles."),(0,r.kt)("p",null,"This library has no transitive dependency and is meant to be lightweight."),(0,r.kt)("h2",{id:"register-properties-files"},"Register Properties files"),(0,r.kt)("p",null,"Any change to the ",(0,r.kt)("inlineCode",{parentName:"p"},"properties")," file should re-trigger the generation for the ",(0,r.kt)("inlineCode",{parentName:"p"},"enums")," for strong\ntyping. ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Gradle")," support this easily. ",(0,r.kt)("inlineCode",{parentName:"p"},"Maven")," has\n",(0,r.kt)("a",{parentName:"p",href:"/docs/installation/maven#be-aware-of-the-annotation-processor-limitations-with-maven"},"some limitations")," to be aware\nof."))}d.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[614],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function o(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=a.createContext({}),p=function(e){var t=a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},u=a.forwardRef((function(e,t){var n=e.components,r=e.mdxType,i=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),u=p(n),m=r,f=u["".concat(l,".").concat(m)]||u[m]||d[m]||i;return n?a.createElement(f,o(o({ref:t},c),{},{components:n})):a.createElement(f,o({ref:t},c))}));function m(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var i=n.length,o=new Array(i);o[0]=u;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s.mdxType="string"==typeof e?e:r,o[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var a=n(7462),r=(n(7294),n(3905));const i={title:"Installation",description:"Java internationalization made easy and safe!"},o=void 0,s={unversionedId:"installation/installation",id:"installation/installation",title:"Installation",description:"Java internationalization made easy and safe!",source:"@site/docs/installation/installation.md",sourceDirName:"installation",slug:"/installation/",permalink:"/docs/installation/",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/installation.md",tags:[],version:"current",frontMatter:{title:"Installation",description:"Java internationalization made easy and safe!"},sidebar:"docs",previous:{title:"Getting Started",permalink:"/docs/getting-started"},next:{title:"Bazel",permalink:"/docs/installation/bazel"}},l={},p=[{value:"Annotation processor",id:"annotation-processor",level:2},{value:"Fluent API",id:"fluent-api",level:2},{value:"Register Properties files",id:"register-properties-files",level:2}],c={toc:p};function d(e){let{components:t,...n}=e;return(0,r.kt)("wrapper",(0,a.Z)({},c,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{type:"info"},(0,r.kt)("p",{parentName:"admonition"},"Java 8+ supported"),(0,r.kt)("p",{parentName:"admonition"},"Maven group id is ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages")," and artifact id ",(0,r.kt)("inlineCode",{parentName:"p"},"l10nmessages"),". "),(0,r.kt)("p",{parentName:"admonition"},"The latest version is ",(0,r.kt)("inlineCode",{parentName:"p"},"1.0.4"),".")),(0,r.kt)("p",null,"Each build system: ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel"),", ",(0,r.kt)("inlineCode",{parentName:"p"},"Gradle")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Maven")," has a slightly different setup, but the main steps\nare:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Set up the annotation processor"),(0,r.kt)("li",{parentName:"ul"},"Add the runtime library / fluent API"),(0,r.kt)("li",{parentName:"ul"},"Register ",(0,r.kt)("inlineCode",{parentName:"li"},"properties")," files")),(0,r.kt)("p",null,"It is recommended to use the annotation processor together with the runtime library but both can be\nused independently. The documentation covers setting up both together."),(0,r.kt)("h2",{id:"annotation-processor"},"Annotation processor"),(0,r.kt)("p",null,"The annotation processor: ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages.L10nPropertiesProcessor")," is used to generate\nenums for strong typing and to perform compile time checks. It must have access to the properties\nfiles through the annotation path or classpath which is build system dependent."),(0,r.kt)("h2",{id:"fluent-api"},"Fluent API"),(0,r.kt)("p",null,"The fluent API: ",(0,r.kt)("inlineCode",{parentName:"p"},"com.pinterest.l10nmessages.L10nMessages")," is used at runtime to load and format\nmessages. Properties files are accessed through the classpath as defined by JDK / ICU resource\nbundles."),(0,r.kt)("p",null,"This library has no transitive dependency and is meant to be lightweight."),(0,r.kt)("h2",{id:"register-properties-files"},"Register Properties files"),(0,r.kt)("p",null,"Any change to the ",(0,r.kt)("inlineCode",{parentName:"p"},"properties")," file should re-trigger the generation for the ",(0,r.kt)("inlineCode",{parentName:"p"},"enums")," for strong\ntyping. ",(0,r.kt)("inlineCode",{parentName:"p"},"Bazel")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"Gradle")," support this easily. ",(0,r.kt)("inlineCode",{parentName:"p"},"Maven")," has\n",(0,r.kt)("a",{parentName:"p",href:"/docs/installation/maven#be-aware-of-the-annotation-processor-limitations-with-maven"},"some limitations")," to be aware\nof."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/2191c1fe.80bda392.js b/assets/js/2191c1fe.b440b918.js similarity index 97% rename from assets/js/2191c1fe.80bda392.js rename to assets/js/2191c1fe.b440b918.js index 852f239..30734d1 100644 --- a/assets/js/2191c1fe.80bda392.js +++ b/assets/js/2191c1fe.b440b918.js @@ -1 +1 @@ -"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[818],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>u});var a=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function r(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=p(t),u=i,g=m["".concat(l,".").concat(u)]||m[u]||d[u]||o;return t?a.createElement(g,r(r({ref:n},c),{},{components:t})):a.createElement(g,r({ref:n},c))}));function u(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,r=new Array(o);r[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,r[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var a=t(7462),i=(t(7294),t(3905));const o={title:"Maven"},r=void 0,s={unversionedId:"installation/maven",id:"installation/maven",title:"Maven",description:"Maven has two different ways to set up annotation processors:",source:"@site/docs/installation/maven.md",sourceDirName:"installation",slug:"/installation/maven",permalink:"/docs/installation/maven",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/maven.md",tags:[],version:"current",frontMatter:{title:"Maven"},sidebar:"docs",previous:{title:"Gradle",permalink:"/docs/installation/gradle"},next:{title:"Resource Bundle",permalink:"/docs/resource-bundle"}},l={},p=[{value:"JDK only",id:"jdk-only",level:2},{value:"Default discovery process",id:"default-discovery-process",level:3},{value:"Explicit configuration of the annotation processor (recommanded)",id:"explicit-configuration-of-the-annotation-processor-recommanded",level:3},{value:"With ICU4J",id:"with-icu4j",level:2},{value:"Be aware of the annotation processor limitations with Maven",id:"be-aware-of-the-annotation-processor-limitations-with-maven",level:2},{value:"Maven plugin",id:"maven-plugin",level:2},{value:"Development / Watcher",id:"development--watcher",level:2}],c={toc:p};function d(e){let{components:n,...t}=e;return(0,i.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Maven")," has two different ways to set up annotation processors:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Default discovery process"),(0,i.kt)("li",{parentName:"ul"},"Explicit configuration (recommended)")),(0,i.kt)("p",null,"Regardless, the main underlying steps are:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Add the runtime dependency"),(0,i.kt)("li",{parentName:"ul"},"Configure the annotation processor")),(0,i.kt)("admonition",{type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"While it is possible to use the annotation processor with Maven projects, there are some limitations\nthat can lead to ",(0,i.kt)("strong",{parentName:"p"},"false positive builds")," or making the developer experience cumbersome. Be aware\nof them and see\n",(0,i.kt)("a",{parentName:"p",href:"#be-aware-of-the-annotation-processor-limitations-with-maven"},"details and workarounds")," below."),(0,i.kt)("p",{parentName:"admonition"},"Consider using the ",(0,i.kt)("a",{parentName:"p",href:"#maven-plugin"},"Maven plugin")," as an alternative.")),(0,i.kt)("h2",{id:"jdk-only"},"JDK only"),(0,i.kt)("h3",{id:"default-discovery-process"},"Default discovery process"),(0,i.kt)("p",null,'Just add the annotation processor\'s library as "compile" dependency to use the default discovery\nprocess. The processor will automatically be detected and the ',(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files will be made\naccessible to the processor via the classpath. The runtime library is made available as a transitive\ndependency."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.3\n \n\n")),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("p",{parentName:"admonition"},"The drawback of this approach is that the annotation processor is declared as ",(0,i.kt)("inlineCode",{parentName:"p"},"compile")," dependency\nwhich is not optimal (vs. only having the runtime library).")),(0,i.kt)("h3",{id:"explicit-configuration-of-the-annotation-processor-recommanded"},"Explicit configuration of the annotation processor (recommanded)"),(0,i.kt)("p",null,'Add a "compile" dependency on the runtime library and configure the annotation process in the\n',(0,i.kt)("inlineCode",{parentName:"p"},"maven-compiler-plugin"),"."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.3\n \n \n \n \n \n maven-compiler-plugin\n \n \n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.3\n \n \n com.pinterest.l10nmessages.L10nPropertiesProcessor\n \n \n org.apache.maven.plugins\n ${maven.compiler.version}\n \n \n \n\n")),(0,i.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,i.kt)("p",null,'Same as "JDK only" and add the ',(0,i.kt)("inlineCode",{parentName:"p"},"icu4j"),' as "compile" dependency.'),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.3\n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n org.apache.maven.plugins\n maven-compiler-plugin\n \n \n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.3\n \n \n com.pinterest.l10nmessages.L10nPropertiesProcessor\n \n \n \n \n \n\n")),(0,i.kt)("h2",{id:"be-aware-of-the-annotation-processor-limitations-with-maven"},"Be aware of the annotation processor limitations with Maven"),(0,i.kt)("p",null,'With Maven (and contrarily to Gradle), it is not possible to register resources as "compile"\ndependencies.'),(0,i.kt)("p",null,"Because of that, when a registered ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file changes, it is not automatically re-processed\nby the annotation processor during the next compilation. To be re-processed, the class that\nregisters the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file using the ",(0,i.kt)("inlineCode",{parentName:"p"},"@L10nProperties")," must be re-compiled. And for that class\nto be re-compiled, it has to be either changed or a full clean compilation performed."),(0,i.kt)("admonition",{type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"To avoid staled ",(0,i.kt)("inlineCode",{parentName:"p"},"enum")," and invalid messages, force a full clean compilation with:\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn clean compile")),(0,i.kt)("p",{parentName:"admonition"},"Consider using the ",(0,i.kt)("a",{parentName:"p",href:"#maven-plugin"},"Maven plugin")," too.")),(0,i.kt)("p",null,"The following example shows the issue. It starts with an initial successful compilation. Then, the\n",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file (and only that file) is changed. The following compilation still succeeds even\nthough we'd expect it to fail as the ",(0,i.kt)("inlineCode",{parentName:"p"},"welcome_user")," message is broken. We'd also expect the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"\nto be re-generated and re-compiled to reflect the ",(0,i.kt)("inlineCode",{parentName:"p"},"bye_up")," key change but instead it is staled."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"$ cat src/main/resources/com/pinterest/l10nmessages/example/Messages.properties\nwelcome_user=Welcome {username}!\nbye=Bye\n\n$ mvn clean compile\n...\n[INFO] BUILD SUCCESS\n\n# only change the properties file\n$ cat src/main/resources/com/pinterest/l10nmessages/example/Messages.properties\nwelcome_user=Welcome {usernam!\nbye_up=Bye\n\n$ nvm compile\n...\n[INFO] Nothing to compile - all classes are up to date\n[INFO] BUILD SUCCESS\n\n$ mvn clean compile\n...\n[ERROR] BUILD FAILURE\n")),(0,i.kt)("h2",{id:"maven-plugin"},"Maven plugin"),(0,i.kt)("p",null,"The Maven plugin: ",(0,i.kt)("inlineCode",{parentName:"p"},"l10nmessages-mvn-plugin")," addresses the\n",(0,i.kt)("a",{parentName:"p",href:"#be-aware-of-the-annotation-processor-limitations-with-maven"},"limitations of the annotation processor"),"\nand can be used as a replacement."),(0,i.kt)("p",null,"To register ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files for processing, use ",(0,i.kt)("inlineCode",{parentName:"p"},"l10nPropertiesList")," element of the plugin\nconfiguration. The same options as with ",(0,i.kt)("inlineCode",{parentName:"p"},"@L10nProperties")," can be provided."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml"},"\n\n \n \n com.pinterest.l10nmessages.Messages\n \n \n com.pinterest.l10nmessages.OtherMessages\n ROOT\n \n \n\n")),(0,i.kt)("p",null,"Runtime dependencies are like with the annotation processor. Only the plugin\n",(0,i.kt)("inlineCode",{parentName:"p"},"l10nmessages-mvn-plugin")," replaces the annotation processor's configuration. If using ",(0,i.kt)("inlineCode",{parentName:"p"},"icu4j")," it\nneeds to be provided as ",(0,i.kt)("inlineCode",{parentName:"p"},"compile")," dependency and as ",(0,i.kt)("inlineCode",{parentName:"p"},"plugin")," dependency"),(0,i.kt)("p",null,"The full configuration looks like:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.3\n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n com.pinterest.l10nmessages\n l10nmessages-mvn-plugin\n 1.0.3\n \n \n \n generate\n \n \n \n \n \n \n com.pinterest.l10nmessages.example.Messages\n \n \n \n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n\n")),(0,i.kt)("p",null,"With the plugin now setup, the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"s generation and the message validation is done by default\nduring the ",(0,i.kt)("inlineCode",{parentName:"p"},"generate-sources")," phase. Any change to the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files will be processed."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"$ mvn generate-sources\n")),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"It is possible to use both the annotation processor and the Maven plugin at the same time. But when\ndoing so, make sure that the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files are only registered once else it will generate\nduplicated ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"s that will break the compilation.")),(0,i.kt)("h2",{id:"development--watcher"},"Development / Watcher"),(0,i.kt)("p",null,"During development, it can become cumbersome to manually call ",(0,i.kt)("inlineCode",{parentName:"p"},"mvn generate-resources")," (or\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn clean compile")," with the anntation processor) every time a new string is added to the\n",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file."),(0,i.kt)("p",null,"Use a watcher to automate the re-generation. For example on Mac OSX:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},'brew install fswatch\nfswatch -e ".*" -i "\\\\.properties$" src/ | xargs -n1 -I{} mvn generate-sources\n')),(0,i.kt)("p",null,"It will also perfectly integrate with IDEs. Choose between executing ",(0,i.kt)("inlineCode",{parentName:"p"},"mvn generate-sources")," or\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn compile")," depending if you want to just generate the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum")," file or if you also want to compile\nit. It is sometimes preferable to delegate the compilation to the IDE instead)."))}d.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[818],{3905:(e,n,t)=>{t.d(n,{Zo:()=>c,kt:()=>u});var a=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function o(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function r(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):r(r({},n),e)),t},c=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},d={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},m=a.forwardRef((function(e,n){var t=e.components,i=e.mdxType,o=e.originalType,l=e.parentName,c=s(e,["components","mdxType","originalType","parentName"]),m=p(t),u=i,g=m["".concat(l,".").concat(u)]||m[u]||d[u]||o;return t?a.createElement(g,r(r({ref:n},c),{},{components:t})):a.createElement(g,r({ref:n},c))}));function u(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var o=t.length,r=new Array(o);r[0]=m;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s.mdxType="string"==typeof e?e:i,r[1]=s;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>s,toc:()=>p});var a=t(7462),i=(t(7294),t(3905));const o={title:"Maven"},r=void 0,s={unversionedId:"installation/maven",id:"installation/maven",title:"Maven",description:"Maven has two different ways to set up annotation processors:",source:"@site/docs/installation/maven.md",sourceDirName:"installation",slug:"/installation/maven",permalink:"/docs/installation/maven",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/maven.md",tags:[],version:"current",frontMatter:{title:"Maven"},sidebar:"docs",previous:{title:"Gradle",permalink:"/docs/installation/gradle"},next:{title:"Resource Bundle",permalink:"/docs/resource-bundle"}},l={},p=[{value:"JDK only",id:"jdk-only",level:2},{value:"Default discovery process",id:"default-discovery-process",level:3},{value:"Explicit configuration of the annotation processor (recommanded)",id:"explicit-configuration-of-the-annotation-processor-recommanded",level:3},{value:"With ICU4J",id:"with-icu4j",level:2},{value:"Be aware of the annotation processor limitations with Maven",id:"be-aware-of-the-annotation-processor-limitations-with-maven",level:2},{value:"Maven plugin",id:"maven-plugin",level:2},{value:"Development / Watcher",id:"development--watcher",level:2}],c={toc:p};function d(e){let{components:n,...t}=e;return(0,i.kt)("wrapper",(0,a.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("p",null,(0,i.kt)("inlineCode",{parentName:"p"},"Maven")," has two different ways to set up annotation processors:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Default discovery process"),(0,i.kt)("li",{parentName:"ul"},"Explicit configuration (recommended)")),(0,i.kt)("p",null,"Regardless, the main underlying steps are:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"Add the runtime dependency"),(0,i.kt)("li",{parentName:"ul"},"Configure the annotation processor")),(0,i.kt)("admonition",{type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"While it is possible to use the annotation processor with Maven projects, there are some limitations\nthat can lead to ",(0,i.kt)("strong",{parentName:"p"},"false positive builds")," or making the developer experience cumbersome. Be aware\nof them and see\n",(0,i.kt)("a",{parentName:"p",href:"#be-aware-of-the-annotation-processor-limitations-with-maven"},"details and workarounds")," below."),(0,i.kt)("p",{parentName:"admonition"},"Consider using the ",(0,i.kt)("a",{parentName:"p",href:"#maven-plugin"},"Maven plugin")," as an alternative.")),(0,i.kt)("h2",{id:"jdk-only"},"JDK only"),(0,i.kt)("h3",{id:"default-discovery-process"},"Default discovery process"),(0,i.kt)("p",null,'Just add the annotation processor\'s library as "compile" dependency to use the default discovery\nprocess. The processor will automatically be detected and the ',(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files will be made\naccessible to the processor via the classpath. The runtime library is made available as a transitive\ndependency."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.4\n \n\n")),(0,i.kt)("admonition",{type:"note"},(0,i.kt)("p",{parentName:"admonition"},"The drawback of this approach is that the annotation processor is declared as ",(0,i.kt)("inlineCode",{parentName:"p"},"compile")," dependency\nwhich is not optimal (vs. only having the runtime library).")),(0,i.kt)("h3",{id:"explicit-configuration-of-the-annotation-processor-recommanded"},"Explicit configuration of the annotation processor (recommanded)"),(0,i.kt)("p",null,'Add a "compile" dependency on the runtime library and configure the annotation process in the\n',(0,i.kt)("inlineCode",{parentName:"p"},"maven-compiler-plugin"),"."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.4\n \n \n \n \n \n maven-compiler-plugin\n \n \n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.4\n \n \n com.pinterest.l10nmessages.L10nPropertiesProcessor\n \n \n org.apache.maven.plugins\n ${maven.compiler.version}\n \n \n \n\n")),(0,i.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,i.kt)("p",null,'Same as "JDK only" and add the ',(0,i.kt)("inlineCode",{parentName:"p"},"icu4j"),' as "compile" dependency.'),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.4\n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n org.apache.maven.plugins\n maven-compiler-plugin\n \n \n \n com.pinterest.l10nmessages\n l10nmessages-proc\n 1.0.4\n \n \n com.pinterest.l10nmessages.L10nPropertiesProcessor\n \n \n \n \n \n\n")),(0,i.kt)("h2",{id:"be-aware-of-the-annotation-processor-limitations-with-maven"},"Be aware of the annotation processor limitations with Maven"),(0,i.kt)("p",null,'With Maven (and contrarily to Gradle), it is not possible to register resources as "compile"\ndependencies.'),(0,i.kt)("p",null,"Because of that, when a registered ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file changes, it is not automatically re-processed\nby the annotation processor during the next compilation. To be re-processed, the class that\nregisters the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file using the ",(0,i.kt)("inlineCode",{parentName:"p"},"@L10nProperties")," must be re-compiled. And for that class\nto be re-compiled, it has to be either changed or a full clean compilation performed."),(0,i.kt)("admonition",{type:"warning"},(0,i.kt)("p",{parentName:"admonition"},"To avoid staled ",(0,i.kt)("inlineCode",{parentName:"p"},"enum")," and invalid messages, force a full clean compilation with:\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn clean compile")),(0,i.kt)("p",{parentName:"admonition"},"Consider using the ",(0,i.kt)("a",{parentName:"p",href:"#maven-plugin"},"Maven plugin")," too.")),(0,i.kt)("p",null,"The following example shows the issue. It starts with an initial successful compilation. Then, the\n",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file (and only that file) is changed. The following compilation still succeeds even\nthough we'd expect it to fail as the ",(0,i.kt)("inlineCode",{parentName:"p"},"welcome_user")," message is broken. We'd also expect the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"\nto be re-generated and re-compiled to reflect the ",(0,i.kt)("inlineCode",{parentName:"p"},"bye_up")," key change but instead it is staled."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"$ cat src/main/resources/com/pinterest/l10nmessages/example/Messages.properties\nwelcome_user=Welcome {username}!\nbye=Bye\n\n$ mvn clean compile\n...\n[INFO] BUILD SUCCESS\n\n# only change the properties file\n$ cat src/main/resources/com/pinterest/l10nmessages/example/Messages.properties\nwelcome_user=Welcome {usernam!\nbye_up=Bye\n\n$ nvm compile\n...\n[INFO] Nothing to compile - all classes are up to date\n[INFO] BUILD SUCCESS\n\n$ mvn clean compile\n...\n[ERROR] BUILD FAILURE\n")),(0,i.kt)("h2",{id:"maven-plugin"},"Maven plugin"),(0,i.kt)("p",null,"The Maven plugin: ",(0,i.kt)("inlineCode",{parentName:"p"},"l10nmessages-mvn-plugin")," addresses the\n",(0,i.kt)("a",{parentName:"p",href:"#be-aware-of-the-annotation-processor-limitations-with-maven"},"limitations of the annotation processor"),"\nand can be used as a replacement."),(0,i.kt)("p",null,"To register ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files for processing, use ",(0,i.kt)("inlineCode",{parentName:"p"},"l10nPropertiesList")," element of the plugin\nconfiguration. The same options as with ",(0,i.kt)("inlineCode",{parentName:"p"},"@L10nProperties")," can be provided."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml"},"\n\n \n \n com.pinterest.l10nmessages.Messages\n \n \n com.pinterest.l10nmessages.OtherMessages\n ROOT\n \n \n\n")),(0,i.kt)("p",null,"Runtime dependencies are like with the annotation processor. Only the plugin\n",(0,i.kt)("inlineCode",{parentName:"p"},"l10nmessages-mvn-plugin")," replaces the annotation processor's configuration. If using ",(0,i.kt)("inlineCode",{parentName:"p"},"icu4j")," it\nneeds to be provided as ",(0,i.kt)("inlineCode",{parentName:"p"},"compile")," dependency and as ",(0,i.kt)("inlineCode",{parentName:"p"},"plugin")," dependency"),(0,i.kt)("p",null,"The full configuration looks like:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-xml",metastring:"title=pom.xml",title:"pom.xml"},"\n \n \n com.pinterest.l10nmessages\n l10nmessages\n 1.0.4\n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n com.pinterest.l10nmessages\n l10nmessages-mvn-plugin\n 1.0.4\n \n \n \n generate\n \n \n \n \n \n \n com.pinterest.l10nmessages.example.Messages\n \n \n \n \n \n com.ibm.icu\n icu4j\n 72.1\n \n \n \n \n \n\n")),(0,i.kt)("p",null,"With the plugin now setup, the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"s generation and the message validation is done by default\nduring the ",(0,i.kt)("inlineCode",{parentName:"p"},"generate-sources")," phase. Any change to the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files will be processed."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},"$ mvn generate-sources\n")),(0,i.kt)("admonition",{type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"It is possible to use both the annotation processor and the Maven plugin at the same time. But when\ndoing so, make sure that the ",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," files are only registered once else it will generate\nduplicated ",(0,i.kt)("inlineCode",{parentName:"p"},"enum"),"s that will break the compilation.")),(0,i.kt)("h2",{id:"development--watcher"},"Development / Watcher"),(0,i.kt)("p",null,"During development, it can become cumbersome to manually call ",(0,i.kt)("inlineCode",{parentName:"p"},"mvn generate-resources")," (or\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn clean compile")," with the anntation processor) every time a new string is added to the\n",(0,i.kt)("inlineCode",{parentName:"p"},"properties")," file."),(0,i.kt)("p",null,"Use a watcher to automate the re-generation. For example on Mac OSX:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-shell"},'brew install fswatch\nfswatch -e ".*" -i "\\\\.properties$" src/ | xargs -n1 -I{} mvn generate-sources\n')),(0,i.kt)("p",null,"It will also perfectly integrate with IDEs. Choose between executing ",(0,i.kt)("inlineCode",{parentName:"p"},"mvn generate-sources")," or\n",(0,i.kt)("inlineCode",{parentName:"p"},"mvn compile")," depending if you want to just generate the ",(0,i.kt)("inlineCode",{parentName:"p"},"enum")," file or if you also want to compile\nit. It is sometimes preferable to delegate the compilation to the IDE instead)."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9c79f53b.34cde490.js b/assets/js/9c79f53b.503fa77e.js similarity index 95% rename from assets/js/9c79f53b.34cde490.js rename to assets/js/9c79f53b.503fa77e.js index b77d38b..5c0bca1 100644 --- a/assets/js/9c79f53b.34cde490.js +++ b/assets/js/9c79f53b.503fa77e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[785],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>u});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(n),u=a,g=m["".concat(s,".").concat(u)]||m[u]||d[u]||i;return n?r.createElement(g,o(o({ref:t},p),{},{components:n})):r.createElement(g,o({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const i={title:"Gradle"},o=void 0,l={unversionedId:"installation/gradle",id:"installation/gradle",title:"Gradle",description:"For Gradle the main steps are:",source:"@site/docs/installation/gradle.md",sourceDirName:"installation",slug:"/installation/gradle",permalink:"/docs/installation/gradle",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/gradle.md",tags:[],version:"current",frontMatter:{title:"Gradle"},sidebar:"docs",previous:{title:"Bazel",permalink:"/docs/installation/bazel"},next:{title:"Maven",permalink:"/docs/installation/maven"}},s={},c=[{value:"JDK only",id:"jdk-only",level:2},{value:"With ICU4J",id:"with-icu4j",level:2}],p={toc:c};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"For ",(0,a.kt)("inlineCode",{parentName:"p"},"Gradle")," the main steps are:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Add the runtime dependency with ",(0,a.kt)("inlineCode",{parentName:"li"},"implementation()")),(0,a.kt)("li",{parentName:"ul"},"Configure the annotation processor using ",(0,a.kt)("inlineCode",{parentName:"li"},"annotationProcessor()")),(0,a.kt)("li",{parentName:"ul"},"Register ",(0,a.kt)("inlineCode",{parentName:"li"},"properties")," files with the annotation processor to re-process files on changes")),(0,a.kt)("h2",{id:"jdk-only"},"JDK only"),(0,a.kt)("p",null,"The library is added for both runtime (",(0,a.kt)("inlineCode",{parentName:"p"},"implementation"),") and annotation processing\n",(0,a.kt)("inlineCode",{parentName:"p"},"annotationProcessor"),"."),(0,a.kt)("p",null,"The runtime library is added using ",(0,a.kt)("inlineCode",{parentName:"p"},"implementation")," entry the the annotation processor with\n",(0,a.kt)("inlineCode",{parentName:"p"},"annotationProcessor")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-kotlin",metastring:"title=build.gradle.kts",title:"build.gradle.kts"},'dependencies {\n implementation("com.pinterest.l10nmessages:l10nmessages:1.0.3")\n annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.3")\n annotationProcessor(files("src/main/resources/**/*.properties"))\n}\n')),(0,a.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,a.kt)("p",null,'Same as "JDK only" and add the ',(0,a.kt)("inlineCode",{parentName:"p"},"icu4j")," dependency to both the annotation processor and runtime\ndependencies"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-kotlin",metastring:"title=build.gradle.kts",title:"build.gradle.kts"},'dependencies {\n implementation("com.pinterest.l10nmessages:l10nmessages:1.0.3")\n implementation("com.ibm.icu:icu4j:72.1")\n\n annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.3")\n annotationProcessor("com.ibm.icu:icu4j:72.1")\n annotationProcessor(files("src/main/resources/**/*.properties"))\n}\n')))}d.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkl10nmessages_website=self.webpackChunkl10nmessages_website||[]).push([[785],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>u});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,i=e.originalType,s=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),m=c(n),u=a,g=m["".concat(s,".").concat(u)]||m[u]||d[u]||i;return n?r.createElement(g,o(o({ref:t},p),{},{components:n})):r.createElement(g,o({ref:t},p))}));function u(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var i=n.length,o=new Array(i);o[0]=m;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:a,o[1]=l;for(var c=2;c{n.r(t),n.d(t,{assets:()=>s,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var r=n(7462),a=(n(7294),n(3905));const i={title:"Gradle"},o=void 0,l={unversionedId:"installation/gradle",id:"installation/gradle",title:"Gradle",description:"For Gradle the main steps are:",source:"@site/docs/installation/gradle.md",sourceDirName:"installation",slug:"/installation/gradle",permalink:"/docs/installation/gradle",draft:!1,editUrl:"https://github.com/pinterest/l10nmessages/edit/main/docs/docs/installation/gradle.md",tags:[],version:"current",frontMatter:{title:"Gradle"},sidebar:"docs",previous:{title:"Bazel",permalink:"/docs/installation/bazel"},next:{title:"Maven",permalink:"/docs/installation/maven"}},s={},c=[{value:"JDK only",id:"jdk-only",level:2},{value:"With ICU4J",id:"with-icu4j",level:2}],p={toc:c};function d(e){let{components:t,...n}=e;return(0,a.kt)("wrapper",(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("p",null,"For ",(0,a.kt)("inlineCode",{parentName:"p"},"Gradle")," the main steps are:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Add the runtime dependency with ",(0,a.kt)("inlineCode",{parentName:"li"},"implementation()")),(0,a.kt)("li",{parentName:"ul"},"Configure the annotation processor using ",(0,a.kt)("inlineCode",{parentName:"li"},"annotationProcessor()")),(0,a.kt)("li",{parentName:"ul"},"Register ",(0,a.kt)("inlineCode",{parentName:"li"},"properties")," files with the annotation processor to re-process files on changes")),(0,a.kt)("h2",{id:"jdk-only"},"JDK only"),(0,a.kt)("p",null,"The library is added for both runtime (",(0,a.kt)("inlineCode",{parentName:"p"},"implementation"),") and annotation processing\n",(0,a.kt)("inlineCode",{parentName:"p"},"annotationProcessor"),"."),(0,a.kt)("p",null,"The runtime library is added using ",(0,a.kt)("inlineCode",{parentName:"p"},"implementation")," entry the the annotation processor with\n",(0,a.kt)("inlineCode",{parentName:"p"},"annotationProcessor")),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-kotlin",metastring:"title=build.gradle.kts",title:"build.gradle.kts"},'dependencies {\n implementation("com.pinterest.l10nmessages:l10nmessages:1.0.4")\n annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.4")\n annotationProcessor(files("src/main/resources/**/*.properties"))\n}\n')),(0,a.kt)("h2",{id:"with-icu4j"},"With ICU4J"),(0,a.kt)("p",null,'Same as "JDK only" and add the ',(0,a.kt)("inlineCode",{parentName:"p"},"icu4j")," dependency to both the annotation processor and runtime\ndependencies"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-kotlin",metastring:"title=build.gradle.kts",title:"build.gradle.kts"},'dependencies {\n implementation("com.pinterest.l10nmessages:l10nmessages:1.0.4")\n implementation("com.ibm.icu:icu4j:72.1")\n\n annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.4")\n annotationProcessor("com.ibm.icu:icu4j:72.1")\n annotationProcessor(files("src/main/resources/**/*.properties"))\n}\n')))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.c54225cc.js b/assets/js/runtime~main.57631990.js similarity index 95% rename from assets/js/runtime~main.c54225cc.js rename to assets/js/runtime~main.57631990.js index 7bd5352..641c3ff 100644 --- a/assets/js/runtime~main.c54225cc.js +++ b/assets/js/runtime~main.57631990.js @@ -1 +1 @@ -(()=>{"use strict";var e,t,r,a,o,n={},f={};function i(e){var t=f[e];if(void 0!==t)return t.exports;var r=f[e]={exports:{}};return n[e].call(r.exports,r,r.exports,i),r.exports}i.m=n,e=[],i.O=(t,r,a,o)=>{if(!r){var n=1/0;for(s=0;s=o)&&Object.keys(i.O).every((e=>i.O[e](r[d])))?r.splice(d--,1):(f=!1,o0&&e[s-1][2]>o;s--)e[s]=e[s-1];e[s]=[r,a,o]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,i.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var o=Object.create(null);i.r(o);var n={};t=t||[null,r({}),r([]),r(r)];for(var f=2&a&&e;"object"==typeof f&&!~t.indexOf(f);f=r(f))Object.getOwnPropertyNames(f).forEach((t=>n[t]=()=>e[t]));return n.default=()=>e,i.d(o,n),o},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((t,r)=>(i.f[r](e,t),t)),[])),i.u=e=>"assets/js/"+({30:"09d5ad39",53:"935f2afb",72:"c3e3ca13",101:"0a3ea1d4",128:"a09c2993",162:"d589d3a7",237:"1df93b7f",290:"bafa151c",337:"8694a7d5",435:"b7d48473",514:"1be78505",578:"6efe4bf0",614:"1e924268",659:"ad046550",669:"a0de1a8c",785:"9c79f53b",818:"2191c1fe",918:"17896441"}[e]||e)+"."+{30:"773177cd",53:"df2c6ef2",72:"e57d7047",101:"bdd1efdd",128:"a3828d7b",162:"7a48459f",237:"83194ae4",290:"6d019782",337:"fa714715",435:"0ab220c3",514:"35c3236f",578:"1a1a70df",614:"b4cbbcc8",659:"654082a0",669:"264bc1dc",785:"34cde490",818:"80bda392",918:"5dd706d6",972:"15abb428"}[e]+".js",i.miniCssF=e=>{},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a={},o="l10nmessages-website:",i.l=(e,t,r,n)=>{if(a[e])a[e].push(t);else{var f,d;if(void 0!==r)for(var c=document.getElementsByTagName("script"),s=0;s{f.onerror=f.onload=null,clearTimeout(b);var o=a[e];if(delete a[e],f.parentNode&&f.parentNode.removeChild(f),o&&o.forEach((e=>e(r))),t)return t(r)},b=setTimeout(l.bind(null,void 0,{type:"timeout",target:f}),12e4);f.onerror=l.bind(null,f.onerror),f.onload=l.bind(null,f.onload),d&&document.head.appendChild(f)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="/",i.gca=function(e){return e={17896441:"918","09d5ad39":"30","935f2afb":"53",c3e3ca13:"72","0a3ea1d4":"101",a09c2993:"128",d589d3a7:"162","1df93b7f":"237",bafa151c:"290","8694a7d5":"337",b7d48473:"435","1be78505":"514","6efe4bf0":"578","1e924268":"614",ad046550:"659",a0de1a8c:"669","9c79f53b":"785","2191c1fe":"818"}[e]||e,i.p+i.u(e)},(()=>{var e={303:0,532:0};i.f.j=(t,r)=>{var a=i.o(e,t)?e[t]:void 0;if(0!==a)if(a)r.push(a[2]);else if(/^(303|532)$/.test(t))e[t]=0;else{var o=new Promise(((r,o)=>a=e[t]=[r,o]));r.push(a[2]=o);var n=i.p+i.u(t),f=new Error;i.l(n,(r=>{if(i.o(e,t)&&(0!==(a=e[t])&&(e[t]=void 0),a)){var o=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;f.message="Loading chunk "+t+" failed.\n("+o+": "+n+")",f.name="ChunkLoadError",f.type=o,f.request=n,a[1](f)}}),"chunk-"+t,t)}},i.O.j=t=>0===e[t];var t=(t,r)=>{var a,o,n=r[0],f=r[1],d=r[2],c=0;if(n.some((t=>0!==e[t]))){for(a in f)i.o(f,a)&&(i.m[a]=f[a]);if(d)var s=d(i)}for(t&&t(r);c{"use strict";var e,t,r,a,o,n={},f={};function i(e){var t=f[e];if(void 0!==t)return t.exports;var r=f[e]={exports:{}};return n[e].call(r.exports,r,r.exports,i),r.exports}i.m=n,e=[],i.O=(t,r,a,o)=>{if(!r){var n=1/0;for(s=0;s=o)&&Object.keys(i.O).every((e=>i.O[e](r[d])))?r.splice(d--,1):(f=!1,o0&&e[s-1][2]>o;s--)e[s]=e[s-1];e[s]=[r,a,o]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},r=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,i.t=function(e,a){if(1&a&&(e=this(e)),8&a)return e;if("object"==typeof e&&e){if(4&a&&e.__esModule)return e;if(16&a&&"function"==typeof e.then)return e}var o=Object.create(null);i.r(o);var n={};t=t||[null,r({}),r([]),r(r)];for(var f=2&a&&e;"object"==typeof f&&!~t.indexOf(f);f=r(f))Object.getOwnPropertyNames(f).forEach((t=>n[t]=()=>e[t]));return n.default=()=>e,i.d(o,n),o},i.d=(e,t)=>{for(var r in t)i.o(t,r)&&!i.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},i.f={},i.e=e=>Promise.all(Object.keys(i.f).reduce(((t,r)=>(i.f[r](e,t),t)),[])),i.u=e=>"assets/js/"+({30:"09d5ad39",53:"935f2afb",72:"c3e3ca13",101:"0a3ea1d4",128:"a09c2993",162:"d589d3a7",237:"1df93b7f",290:"bafa151c",337:"8694a7d5",435:"b7d48473",514:"1be78505",578:"6efe4bf0",614:"1e924268",659:"ad046550",669:"a0de1a8c",785:"9c79f53b",818:"2191c1fe",918:"17896441"}[e]||e)+"."+{30:"773177cd",53:"df2c6ef2",72:"e57d7047",101:"250ffd74",128:"a3828d7b",162:"7a48459f",237:"83194ae4",290:"6d019782",337:"fa714715",435:"0ab220c3",514:"35c3236f",578:"1a1a70df",614:"82198e31",659:"654082a0",669:"264bc1dc",785:"503fa77e",818:"b440b918",918:"5dd706d6",972:"15abb428"}[e]+".js",i.miniCssF=e=>{},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),a={},o="l10nmessages-website:",i.l=(e,t,r,n)=>{if(a[e])a[e].push(t);else{var f,d;if(void 0!==r)for(var c=document.getElementsByTagName("script"),s=0;s{f.onerror=f.onload=null,clearTimeout(b);var o=a[e];if(delete a[e],f.parentNode&&f.parentNode.removeChild(f),o&&o.forEach((e=>e(r))),t)return t(r)},b=setTimeout(l.bind(null,void 0,{type:"timeout",target:f}),12e4);f.onerror=l.bind(null,f.onerror),f.onload=l.bind(null,f.onload),d&&document.head.appendChild(f)}},i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.p="/",i.gca=function(e){return e={17896441:"918","09d5ad39":"30","935f2afb":"53",c3e3ca13:"72","0a3ea1d4":"101",a09c2993:"128",d589d3a7:"162","1df93b7f":"237",bafa151c:"290","8694a7d5":"337",b7d48473:"435","1be78505":"514","6efe4bf0":"578","1e924268":"614",ad046550:"659",a0de1a8c:"669","9c79f53b":"785","2191c1fe":"818"}[e]||e,i.p+i.u(e)},(()=>{var e={303:0,532:0};i.f.j=(t,r)=>{var a=i.o(e,t)?e[t]:void 0;if(0!==a)if(a)r.push(a[2]);else if(/^(303|532)$/.test(t))e[t]=0;else{var o=new Promise(((r,o)=>a=e[t]=[r,o]));r.push(a[2]=o);var n=i.p+i.u(t),f=new Error;i.l(n,(r=>{if(i.o(e,t)&&(0!==(a=e[t])&&(e[t]=void 0),a)){var o=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;f.message="Loading chunk "+t+" failed.\n("+o+": "+n+")",f.name="ChunkLoadError",f.type=o,f.request=n,a[1](f)}}),"chunk-"+t,t)}},i.O.j=t=>0===e[t];var t=(t,r)=>{var a,o,n=r[0],f=r[1],d=r[2],c=0;if(n.some((t=>0!==e[t]))){for(a in f)i.o(f,a)&&(i.m[a]=f[a]);if(d)var s=d(i)}for(t&&t(r);c Annotation Processor | L10nMessages - + @@ -37,7 +37,7 @@ modify the keys accordingly. If that's not possible, use ToJavaIdentifiers.ESCAPING_ONLY instead. All invalid characters will be replaced with the escape sequence. The drawback will be less natural identifiers.

Properties KeyJava identifier
collision.issuecollision_u46_issue
- + \ No newline at end of file diff --git a/docs/caching/index.html b/docs/caching/index.html index ae55b26..ef14028 100644 --- a/docs/caching/index.html +++ b/docs/caching/index.html @@ -4,7 +4,7 @@ Caching | L10nMessages - + @@ -19,7 +19,7 @@ MessageFormat before sharing the L10nMessages instance between multiple threads.

Consider having 1 instance of L10nMessages per thread, or to have some sort of synchronization around the MessageFormat instance.

From the ICU4J documentation:

MessageFormats are not synchronized.

It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

- + \ No newline at end of file diff --git a/docs/examples/index.html b/docs/examples/index.html index 84c09c9..c3f7d02 100644 --- a/docs/examples/index.html +++ b/docs/examples/index.html @@ -4,13 +4,13 @@ Examples | L10nMessages - + - + \ No newline at end of file diff --git a/docs/fluent-api/index.html b/docs/fluent-api/index.html index 1803ff9..37b37ee 100644 --- a/docs/fluent-api/index.html +++ b/docs/fluent-api/index.html @@ -4,7 +4,7 @@ Fluent API | L10nMessages - + @@ -60,7 +60,7 @@ JDK usually set the messageFormatAdapterProviders at the annotation level to get the proper message format validation.


@L10nProperties(
baseName = "com.pinterest.l10nmessages.example.Messages",
messageFormatAdapterProviders = MessageFormatAdapterProviders.JDK)
class Example {

{
L10nMessages<MessagesNamed> m = L10nMessages.builder(Messages.class).build();
System.out.println(m.format(MessagesNamed.welcome_user, "0", "Mary"));
}
}

Or just set it up on the builder

class Example {

{
L10nMessages<String> m = L10nMessages.<String>builder()
.resourceBundleName("com.pinterest.l10nmessages.example.Messages")
.messageFormatAdapterProvider(MessageFormatAdapterProviders.JDK)
.build();
System.out.println(m.format("welcome_user", "0", "Mary"));
}
}
Also works as an independent formatter Just looking for message formatting with named

arguments in Java?

The formatter can be used directly and since the library is lightweight and has no dependencies that can be a good option.

class Example {

{
MessageFormatAdapter mf =
MessageFormatAdapterProviders.JDK_NAMED_ARGS.get("Welcome {username}", Locale.ROOT);
System.out.println(mf.format(ImmutableMap.of("username", "Mary")));
}
}
- + \ No newline at end of file diff --git a/docs/getting-started/index.html b/docs/getting-started/index.html index 5ff0abf..4328a7c 100644 --- a/docs/getting-started/index.html +++ b/docs/getting-started/index.html @@ -4,7 +4,7 @@ Getting Started | L10nMessages - + @@ -14,7 +14,7 @@ starting from scratch.

Create a resource bundle

Create a root file: Messages.properties in the com.pinterest.l10nmessages.example package.

The corresponding resource bundle baseName is com.pinterest.l10nmessages.example.Messages.

UTF-8 is the recommended encoding for the properties files.

In a project that follows the Maven layout, the file would be:

src/resources/java/com/pinterest/l10nmessages/example/Messages.properties
welcome_user=Welcome {username}!

Register the resource bundle with @L10nProperties

Add the @L10nProperties annotation to the application class to register the resource bundle with the annotation processor.

src/main/java/com/pinterest/l10nmessages/example/Application.java
import com.pinterest.l10nmessages.L10nProperties;

@L10nProperties(baseName = "com.pinterest.l10nmessages.example.Messages")
public class Application {

}

Enum generated by the annotation processor

Compile your project. The annotation processor should generate the following enum:

target/generated-sources/annotations/com/pinterest/l10nmessages/example/Messages.java
package com.pinterest.l10nmessages.example;

public enum Messages {
welcome_user("welcome_user");

public static final String BASENAME = "com.pinterest.l10nmessages.example.Messages";
// ...
}

Strong typing using Enum

That enum can be used to create the L10nMessages instance and then to format a message using the typed key: Messages.welcome_user. The argument: username is provided as a key/value pair.

src/main/java/com/pinterest/l10nmessages/example/Application.java
import com.pinterest.l10nmessages.L10nMessages;
import com.pinterest.l10nmessages.L10nProperties;

@L10nProperties(baseName = "com.pinterest.l10nmessages.example.Messages")
public class Application {

public static void main(String[] args) {
L10nMessages<Messages> m = L10nMessages.builder(Messages.class).build();
String localizedMsg = m.format(Messages.welcome_user, "username", "Mary");
System.out.println(localizedMsg);
// Welcome Mary!
}
}

For extra typing, consider argument names typing.

Localization

Localize the root properties file by creating the file Messages_fr.properties for "French"

welcome_user=Bienvenue {username}!

Specify the locale wanted for the messages


@L10nProperties(baseName = "com.pinterest.l10nmessages.example.Messages")
public class Application {

public static void main(String[] args) {
L10nMessages<Messages> m = L10nMessages.builder(Messages.class)
.locale(Locale.FRENCH)
.build();
String localizedMsg = m.format(Messages.welcome_user, "username", "Mary");
System.out.prinln(localizedMsg);
// Bienvenue Mary!
}
}

For advanced message formatting and localization, see the ICU4J guide.

- + \ No newline at end of file diff --git a/docs/icu4j/index.html b/docs/icu4j/index.html index 7b00cf0..9da8fdf 100644 --- a/docs/icu4j/index.html +++ b/docs/icu4j/index.html @@ -4,7 +4,7 @@ ICU4J | L10nMessages - + @@ -47,7 +47,7 @@ argument to handle the empty list and the list with a single element.

info

It is recommended to write full sentences, hence to move the arguments to the outer part of the messages. The plural arguments should be nested inside the select argument that is used for the gender.

en.properties
favorite_numbers={userGender, select, \
female {{numbersCount, plural, \
=0 {She has no favorite numbers} \
one {Her favorite number is {numbers}} \
other {Her favorite numbers are {numbers}}}} \
male {{numbersCount, plural, \
=0 {He has no favorite numbers} \
one {His favorite number is {numbers}} \
other {His favorite numbers are {numbers}}}} \
other {{numbersCount, plural, \
=0 {They have no favorite numbers} \
one {Their favorite number is {numbers}} \
other {Their favorite numbers are {numbers}}}} \
}
fr.properties
favorite_numbers={userGender, select, \
female {{numbersCount, plural, \
=0 {Elle n'a pas de nombre préferé} \
one {Son nombre préferé est {numbers}} \
other {Ses nombres préferés sont {numbers}}}} \
male {{numbersCount, plural, \
=0 {Il n'a pas de nombre préferé} \
one {Son nombre préferé est {numbers}} \
other {Ses nombres préferés sont {numbers}}}} \
other {{numbersCount, plural, \
=0 {Il/Elle n'a pas de nombre préferé} \
one {Son nombre préferé est {numbers}} \
other {Ses nombres préferés sont {numbers}}}} \
}
class Example {

{
L10nMessages<Messages> m = L10nMessages.builder(Messages.class).build();
ListFormatter lf = ListFormatter.getInstance();
Stream.of("female", "male", "other").forEach(userGender ->
Stream.of(Arrays.asList(), Arrays.asList("1"), Arrays.asList("3", "7"))
.forEach(numbers -> System.out.println(
m.format(favorite_numbers, "numbers", lf.format(numbers),
"numbersCount", numbers.size(), "userGender", userGender))));

// She has no favorite numbers
// Her favorite number is 1
// Her favorite numbers are 3 and 7

// He has no favorite numbers
// His favorite number is 1
// His favorite numbers are 3 and 7

// They have no favorite numbers
// Their favorite number is 1
// Their favorite numbers are 3 and 7
}

{
L10nMessages<Messages> m = L10nMessages.builder(Messages.class).locale(Locale.FRANCE).build();
ListFormatter lf = ListFormatter.getInstance(Locale.FRANCE);
Stream.of("female", "male", "other").forEach(gender ->
Stream.of(Arrays.asList(), Arrays.asList("1"), Arrays.asList("3", "7"))
.forEach(numbers -> System.out.println(
m.format(favorite_numbers, "numbers", lf.format(numbers),
"numbersCount", numbers.size(), "userGender", gender))));

// Elle n'a pas de nombre préferé
// Son nombre préferé est 1
// Ses nombres préferés sont 3 et 7

// Il n'a pas de nombre préferé
// Son nombre préferé est 1
// Ses nombres préferés sont 3 et 7

// Il/Elle n'a pas de nombre préferé
// Son nombre préferé est 1
// Ses nombres préferés sont 3 et 7
}
}

- + \ No newline at end of file diff --git a/docs/installation/bazel/index.html b/docs/installation/bazel/index.html index d8ba0c6..f8ffbd3 100644 --- a/docs/installation/bazel/index.html +++ b/docs/installation/bazel/index.html @@ -4,7 +4,7 @@ Bazel | L10nMessages - + @@ -13,8 +13,8 @@ files

BUILD
java_plugin(
name="l10nmessages_proc",
processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",
deps=[
"@maven//:com_pinterest_l10nmessages_l10nmessages_proc",
"@maven//:com_pinterest_l10nmessages_l10nmessages"
],
resources=["l10nresources"]
)

In java_binary, add the resources previously define in resources, register the annotation processor in plugins and finally add a dependency on the library runtime in deps

BUILD
java_binary(
name="l10nbazel",
srcs=glob(["src/main/java/**/*.java"]),
resources=["l10nresources"],
plugins=["l10nmessages_proc"],
deps=[
"@maven//:com_pinterest_l10nmessages_l10nmessages"
],
main_class="com.pinterest.l10nmessages.example.Application",
)

With ICU4J

Same as "JDK only" and add the icu4j dependency to both the annotation processor and runtime dependencies

BUILD

filegroup(
name="l10nresources",
srcs=glob(["src/main/resources/**/*.properties"])
)

java_plugin(
name="l10nmessages_proc",
processor_class="com.pinterest.l10nmessages.L10nPropertiesProcessor",
deps=[
"@maven//:com_pinterest_l10nmessages_l10nmessages_proc",
"@maven//:com_pinterest_l10nmessages_l10nmessages",
"@maven//:com_ibm_icu_icu4j"
],
resources=["l10nresources"]
)

java_binary(
name="l10nbazel",
srcs=glob(["src/main/java/**/*.java"]),
resources=["l10nresources"],
plugins=["l10nmessages_proc"],
deps=[
"@maven//:com_pinterest_l10nmessages_l10nmessages",
"@maven//:com_ibm_icu_icu4j"
],
main_class="com.pinterest.l10nmessages.example.Application",
)

External dependencies

Use rules_jvm_external to fetch external -dependencies from Maven.

RULES_JVM_EXTERNAL_TAG = "4.2"
RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"

http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
artifacts = [
"com.ibm.icu:icu4j:72.1"
"com.pinterest.l10nmessages:l10nmessages:1.0.3"
"com.pinterest.l10nmessages:l10nmessages-proc:1.0.3"
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
- +dependencies from Maven.

RULES_JVM_EXTERNAL_TAG = "4.2"
RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"

http_archive(
name = "rules_jvm_external",
strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
sha256 = RULES_JVM_EXTERNAL_SHA,
url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
artifacts = [
"com.ibm.icu:icu4j:72.1"
"com.pinterest.l10nmessages:l10nmessages:1.0.4"
"com.pinterest.l10nmessages:l10nmessages-proc:1.0.4"
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
+ \ No newline at end of file diff --git a/docs/installation/gradle/index.html b/docs/installation/gradle/index.html index a813d39..f34cc24 100644 --- a/docs/installation/gradle/index.html +++ b/docs/installation/gradle/index.html @@ -4,16 +4,16 @@ Gradle | L10nMessages - +

Gradle

For Gradle the main steps are:

  • Add the runtime dependency with implementation()
  • Configure the annotation processor using annotationProcessor()
  • Register properties files with the annotation processor to re-process files on changes

JDK only

The library is added for both runtime (implementation) and annotation processing annotationProcessor.

The runtime library is added using implementation entry the the annotation processor with -annotationProcessor

build.gradle.kts
dependencies {
implementation("com.pinterest.l10nmessages:l10nmessages:1.0.3")
annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.3")
annotationProcessor(files("src/main/resources/**/*.properties"))
}

With ICU4J

Same as "JDK only" and add the icu4j dependency to both the annotation processor and runtime -dependencies

build.gradle.kts
dependencies {
implementation("com.pinterest.l10nmessages:l10nmessages:1.0.3")
implementation("com.ibm.icu:icu4j:72.1")

annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.3")
annotationProcessor("com.ibm.icu:icu4j:72.1")
annotationProcessor(files("src/main/resources/**/*.properties"))
}
- +annotationProcessor

build.gradle.kts
dependencies {
implementation("com.pinterest.l10nmessages:l10nmessages:1.0.4")
annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.4")
annotationProcessor(files("src/main/resources/**/*.properties"))
}

With ICU4J

Same as "JDK only" and add the icu4j dependency to both the annotation processor and runtime +dependencies

build.gradle.kts
dependencies {
implementation("com.pinterest.l10nmessages:l10nmessages:1.0.4")
implementation("com.ibm.icu:icu4j:72.1")

annotationProcessor("com.pinterest.l10nmessages:l10nmessages-proc:1.0.4")
annotationProcessor("com.ibm.icu:icu4j:72.1")
annotationProcessor(files("src/main/resources/**/*.properties"))
}
+ \ No newline at end of file diff --git a/docs/installation/index.html b/docs/installation/index.html index 922c823..cab354f 100644 --- a/docs/installation/index.html +++ b/docs/installation/index.html @@ -4,12 +4,12 @@ Installation | L10nMessages - +
-

Installation

info

Java 8+ supported

Maven group id is com.pinterest.l10nmessages and artifact id l10nmessages.

The latest version is 1.0.3.

Each build system: Bazel, Gradle and Maven has a slightly different setup, but the main steps +

Installation

info

Java 8+ supported

Maven group id is com.pinterest.l10nmessages and artifact id l10nmessages.

The latest version is 1.0.4.

Each build system: Bazel, Gradle and Maven has a slightly different setup, but the main steps are:

  • Set up the annotation processor
  • Add the runtime library / fluent API
  • Register properties files

It is recommended to use the annotation processor together with the runtime library but both can be used independently. The documentation covers setting up both together.

Annotation processor

The annotation processor: com.pinterest.l10nmessages.L10nPropertiesProcessor is used to generate enums for strong typing and to perform compile time checks. It must have access to the properties @@ -19,7 +19,7 @@ typing. Bazel and Gradle support this easily. Maven has some limitations to be aware of.

- + \ No newline at end of file diff --git a/docs/installation/maven/index.html b/docs/installation/maven/index.html index 66d245e..194c76c 100644 --- a/docs/installation/maven/index.html +++ b/docs/installation/maven/index.html @@ -4,7 +4,7 @@ Maven | L10nMessages - + @@ -15,9 +15,9 @@ details and workarounds below.

Consider using the Maven plugin as an alternative.

JDK only

Default discovery process

Just add the annotation processor's library as "compile" dependency to use the default discovery process. The processor will automatically be detected and the properties files will be made accessible to the processor via the classpath. The runtime library is made available as a transitive -dependency.

pom.xml
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
note

The drawback of this approach is that the annotation processor is declared as compile dependency +dependency.

pom.xml
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
note

The drawback of this approach is that the annotation processor is declared as compile dependency which is not optimal (vs. only having the runtime library).

Explicit configuration of the annotation processor (recommanded)

Add a "compile" dependency on the runtime library and configure the annotation process in the -maven-compiler-plugin.

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.3</version>
</dependency>
</annotationProcessorPaths>
<annotationProcessors>com.pinterest.l10nmessages.L10nPropertiesProcessor
</annotationProcessors>
</configuration>
<groupId>org.apache.maven.plugins</groupId>
<version>${maven.compiler.version}</version>
</plugin>
</plugins>
</build>
</project>

With ICU4J

Same as "JDK only" and add the icu4j as "compile" dependency.

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.3</version>
</dependency>
</annotationProcessorPaths>
<annotationProcessors>com.pinterest.l10nmessages.L10nPropertiesProcessor
</annotationProcessors>
</configuration>
</plugin>
</plugins>
</build>
</project>

Be aware of the annotation processor limitations with Maven

With Maven (and contrarily to Gradle), it is not possible to register resources as "compile" +maven-compiler-plugin.

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.4</version>
</dependency>
</annotationProcessorPaths>
<annotationProcessors>com.pinterest.l10nmessages.L10nPropertiesProcessor
</annotationProcessors>
</configuration>
<groupId>org.apache.maven.plugins</groupId>
<version>${maven.compiler.version}</version>
</plugin>
</plugins>
</build>
</project>

With ICU4J

Same as "JDK only" and add the icu4j as "compile" dependency.

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-proc</artifactId>
<version>1.0.4</version>
</dependency>
</annotationProcessorPaths>
<annotationProcessors>com.pinterest.l10nmessages.L10nPropertiesProcessor
</annotationProcessors>
</configuration>
</plugin>
</plugins>
</build>
</project>

Be aware of the annotation processor limitations with Maven

With Maven (and contrarily to Gradle), it is not possible to register resources as "compile" dependencies.

Because of that, when a registered properties file changes, it is not automatically re-processed by the annotation processor during the next compilation. To be re-processed, the class that registers the properties file using the @L10nProperties must be re-compiled. And for that class @@ -30,7 +30,7 @@ and can be used as a replacement.

To register properties files for processing, use l10nPropertiesList element of the plugin configuration. The same options as with @L10nProperties can be provided.


<configuration>
<l10nPropertiesList>
<l10nProperties>
<baseName>com.pinterest.l10nmessages.Messages</baseName>
</l10nProperties>
<l10nProperties>
<baseName>com.pinterest.l10nmessages.OtherMessages</baseName>
<messageFormatValidationTargets>ROOT</messageFormatValidationTargets>
</l10nProperties>
</l10nPropertiesList>
</configuration>

Runtime dependencies are like with the annotation processor. Only the plugin l10nmessages-mvn-plugin replaces the annotation processor's configuration. If using icu4j it -needs to be provided as compile dependency and as plugin dependency

The full configuration looks like:

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-mvn-plugin</artifactId>
<version>1.0.3</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<l10nPropertiesList>
<l10nProperties>
<baseName>com.pinterest.l10nmessages.example.Messages</baseName>
</l10nProperties>
</l10nPropertiesList>
</configuration>
<dependencies>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

With the plugin now setup, the enums generation and the message validation is done by default +needs to be provided as compile dependency and as plugin dependency

The full configuration looks like:

pom.xml
<project>
<dependencies>
<dependency>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.pinterest.l10nmessages</groupId>
<artifactId>l10nmessages-mvn-plugin</artifactId>
<version>1.0.4</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<l10nPropertiesList>
<l10nProperties>
<baseName>com.pinterest.l10nmessages.example.Messages</baseName>
</l10nProperties>
</l10nPropertiesList>
</configuration>
<dependencies>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
<version>72.1</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>

With the plugin now setup, the enums generation and the message validation is done by default during the generate-sources phase. Any change to the properties files will be processed.

$ mvn generate-sources
caution

It is possible to use both the annotation processor and the Maven plugin at the same time. But when doing so, make sure that the properties files are only registered once else it will generate duplicated enums that will break the compilation.

Development / Watcher

During development, it can become cumbersome to manually call mvn generate-resources (or @@ -38,7 +38,7 @@ properties file.

Use a watcher to automate the re-generation. For example on Mac OSX:

brew install fswatch
fswatch -e ".*" -i "\\.properties$" src/ | xargs -n1 -I{} mvn generate-sources

It will also perfectly integrate with IDEs. Choose between executing mvn generate-sources or mvn compile depending if you want to just generate the enum file or if you also want to compile it. It is sometimes preferable to delegate the compilation to the IDE instead).

- + \ No newline at end of file diff --git a/docs/introduction/index.html b/docs/introduction/index.html index 247068c..d2465af 100644 --- a/docs/introduction/index.html +++ b/docs/introduction/index.html @@ -4,7 +4,7 @@ Introduction | L10nMessages - + @@ -44,7 +44,7 @@ best practices with ICU4J are also documented.

Safer that "plain" Java

Plain Java internationalization lacks in type safety and message format validation. Default error handling will hard fail which might not be the best behavior for production systems. L10nMessages privileges graceful fallbacks and provides hooks to monitor failures.

- + \ No newline at end of file diff --git a/docs/resource-bundle/index.html b/docs/resource-bundle/index.html index be098d3..1e7ae82 100644 --- a/docs/resource-bundle/index.html +++ b/docs/resource-bundle/index.html @@ -4,7 +4,7 @@ Resource Bundle | L10nMessages - + @@ -36,7 +36,7 @@ default. The properties files can use either form. If the default form is missing it will attempt to load the alternate form.

Other ResourceBundle types

The fluent API can use any customized ResourceBundle. The annotation processor is only useful for the ones that are backed by properties files.

- + \ No newline at end of file diff --git a/index.html b/index.html index ae894d1..401a788 100644 --- a/index.html +++ b/index.html @@ -4,13 +4,13 @@ L10nMessages - +

L10nMessages

Java Internationalization made easy!

Lightweight

Lightweight

Rely on Java standard APIs, no extra dependency required. Optional ICU4J integration.

Easy to Use

Easy to Use

Provides a fluent API to load and format localized messages

Safer

Safer

Catch issues at build time! Minimize runtime errors with strong typing and message format validation.

- + \ No newline at end of file