@atlassian/i18n-properties-loader 0.0.0-snapshot.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,149 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
+
6
+ ## 0.0.0-snapshot.0 (2024-12-12)
7
+
8
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
9
+
10
+
11
+
12
+
13
+
14
+ ### [1.0.13](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.13..@atlassian/i18n-properties-loader@1.0.12) (2024-06-25)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **soy-loader:** [SPFE-1067](https://ecosystem.atlassian.net/browse/SPFE-1067) - ensure soy-loader accepts webpack 4 as a peer dependency and add system-level tests for working with all supported webpack versions ([3d8fe4e](https://bitbucket.org/atlassianlabs/fe-server/commits/3d8fe4e97c7af231c32dacf860b4fa54e08053fa))
20
+
21
+
22
+
23
+ ### [1.0.12](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.12..@atlassian/i18n-properties-loader@1.0.11) (2024-05-28)
24
+
25
+ ### Bug Fixes
26
+
27
+ ### [1.0.11](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.11..@atlassian/i18n-properties-loader@1.0.10) (2024-05-13)
28
+
29
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
30
+
31
+ ### 1.0.10 (2024-04-05)
32
+
33
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
34
+
35
+ ### 1.0.9 (2022-02-10)
36
+
37
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
38
+
39
+ ### [1.0.8](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.8..@atlassian/i18n-properties-loader@1.0.7) (2021-11-17)
40
+
41
+ ### Bug Fixes
42
+
43
+ - Update webpack depndency ([00fc73e](https://bitbucket.org/atlassianlabs/fe-server/commits/00fc73e95ad4a2f89ee4fd3561ab3fb60d1b9516))
44
+
45
+ ### [1.0.7](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.7..@atlassian/i18n-properties-loader@1.0.6) (2021-10-26)
46
+
47
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
48
+
49
+ ### [1.0.6](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.6..@atlassian/i18n-properties-loader@1.0.5) (2021-10-22)
50
+
51
+ ### Bug Fixes
52
+
53
+ - **ci:** update webpack versions when running integration tests ([009dd61](https://bitbucket.org/atlassianlabs/fe-server/commits/009dd61f36a784d3fef7b6d6fa7214c5cc16b8b8))
54
+
55
+ ### [1.0.5](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.5..@atlassian/i18n-properties-loader@1.0.4) (2021-10-14)
56
+
57
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
58
+
59
+ ### [1.0.4](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.4..@atlassian/i18n-properties-loader@1.0.3) (2021-10-08)
60
+
61
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
62
+
63
+ ### [1.0.3](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.3..@atlassian/i18n-properties-loader@1.0.2) (2021-09-24)
64
+
65
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
66
+
67
+ ### [1.0.2](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.2..@atlassian/i18n-properties-loader@1.0.1) (2021-09-22)
68
+
69
+ - Update internal dependencies
70
+
71
+ ### Bug Fixes
72
+
73
+ - rename configuration passed to schema validation util ([bb4b6a2](https://bitbucket.org/atlassianlabs/fe-server/commits/bb4b6a2791672a36b019ed7c99915cc8f77e308e))
74
+ - **release:** fix release script for the wrm package ([482efe2](https://bitbucket.org/atlassianlabs/fe-server/commits/482efe2d2262209926a775e56da3df6a89c54f95))
75
+
76
+ ### [1.0.1](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.1..@atlassian/i18n-properties-loader@1.0.0) (2021-08-26)
77
+
78
+ **Note:** We updated internal dependencies
79
+
80
+ ## [1.0.0](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@1.0.0..@atlassian/i18n-properties-loader@0.10.1) (2021-07-01)
81
+
82
+ ### ⚠ BREAKING CHANGES
83
+
84
+ - We removed support for Node 10. The minimum required version is Node 12 now.
85
+
86
+ ### Features
87
+
88
+ - drop support for Node 10 ([2ef1e83](https://bitbucket.org/atlassianlabs/fe-server/commits/2ef1e831cc30f0ec78884d72815d773ae401cc7e))
89
+
90
+ ### [0.10.1](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.10.1..@atlassian/i18n-properties-loader@0.10.0) (2021-03-08)
91
+
92
+ ### Bug Fixes
93
+
94
+ - **deps:** remove webpack cli dependency ([c957fb3](https://bitbucket.org/atlassianlabs/fe-server/commits/c957fb3741348478c885d4af443b14717ea02c95))
95
+ - **deps:** SPFE-346 Update ajv to fix vulnerabilities ([10cba18](https://bitbucket.org/atlassianlabs/fe-server/commits/10cba18c82fd7d4c368b8bb7cfab7d8eada56cf7))
96
+ - **deps:** update dependency schema-utils to v3 ([ce193c2](https://bitbucket.org/atlassianlabs/fe-server/commits/ce193c298dc28abf175939b8a1f86124e0e5f4cc))
97
+ - **deps:** Update Node version ([1dadcca](https://bitbucket.org/atlassianlabs/fe-server/commits/1dadcca42ac461410dabd8e844249cdf80e516a9))
98
+
99
+ ## 0.10.0 (2021-01-18)
100
+
101
+ - feat: SPFE-275 Add support for webpack 5 to soy-loader ([edc7190](https://bitbucket.org/atlassianlabs/fe-server/commits/edc7190))
102
+
103
+ ## 0.10.0-alpha.0 (2021-01-13)
104
+
105
+ - feat: SPFE-268 Add support for webpack 5 ([5a8b215](https://bitbucket.org/atlassianlabs/fe-server/commits/5a8b215))
106
+
107
+ ## 0.9.0 (2020-06-25)
108
+
109
+ - chore: mark the exported RegExp as internals ([b487105](https://bitbucket.org/atlassianlabs/fe-server/commits/b487105))
110
+ - chore: migrate soy-loader tests to jest ([148dbef](https://bitbucket.org/atlassianlabs/fe-server/commits/148dbef))
111
+ - chore: run all tests with jest ([bd4f4e2](https://bitbucket.org/atlassianlabs/fe-server/commits/bd4f4e2))
112
+ - chore: update script commands ([d717342](https://bitbucket.org/atlassianlabs/fe-server/commits/d717342))
113
+ - fix(issue #4): add test cases that prove the quotations doesn't work well ([1012d1b](https://bitbucket.org/atlassianlabs/fe-server/commits/1012d1b)), closes [#4](https://bitbucket.org/atlassianlabs/fe-server/issue/4)
114
+ - fix(issue #4): Fix the message quotation that was inconsistent with Java MessageFormat spec https:// ([1572341](https://bitbucket.org/atlassianlabs/fe-server/commits/1572341))
115
+ - chore: update dependencies ([38f5a33](https://bitbucket.org/atlassianlabs/fe-server/commits/38f5a33))
116
+
117
+ ## 0.8.0 (2020-05-11)
118
+
119
+ - chore: Add note about minimal requirements ([ee38cec](https://bitbucket.org/atlassianlabs/fe-server/commits/ee38cec))
120
+ - chore: downgrade to Node version 10 ([9fc7bab](https://bitbucket.org/atlassianlabs/fe-server/commits/9fc7bab))
121
+ - chore: Update minimal Node version to version 12 so we can support 'String.proptotype.matchall' ([cb0ed25](https://bitbucket.org/atlassianlabs/fe-server/commits/cb0ed25))
122
+
123
+ ## [0.7.4](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.7.4..@atlassian/i18n-properties-loader@0.7.3) (2020-04-21)
124
+
125
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
126
+
127
+ ## [0.7.3](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.7.3..@atlassian/i18n-properties-loader@0.7.1) (2020-02-07)
128
+
129
+ ### Bug Fixes
130
+
131
+ - remove the console.log ([3d92754](https://bitbucket.org/atlassianlabs/fe-server/commits/3d9275465820339e6b8330ad3b6ec6cac023f34e))
132
+
133
+ ## [0.7.2](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.7.2..@atlassian/i18n-properties-loader@0.7.1) (2020-01-28)
134
+
135
+ ### Bug Fixes
136
+
137
+ - remove the console.log ([3d92754](https://bitbucket.org/atlassianlabs/fe-server/commits/3d9275465820339e6b8330ad3b6ec6cac023f34e))
138
+
139
+ ## [0.7.1](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.7.1..@atlassian/i18n-properties-loader@0.7.0) (2020-01-27)
140
+
141
+ **Note:** Version bump only for package @atlassian/i18n-properties-loader
142
+
143
+ # [0.7.0](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.7.0..@atlassian/i18n-properties-loader@0.5.0) (2020-01-25)
144
+
145
+ ### Features
146
+
147
+ - **webpack:** Add missing compatibility for native ESM and ts-loader ([afa4a1f](https://bitbucket.org/atlassianlabs/fe-server/commits/afa4a1f95ee74d6491a63699469bb54b3c515b55))
148
+
149
+ # [0.6.0](https://bitbucket.org/atlassianlabs/fe-server/branches/compare/@atlassian/i18n-properties-loader@0.6.0..@atlassian/i18n-properties-loader@0.5.0) (2020-01-25)
@@ -0,0 +1,73 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ - Using welcoming and inclusive language
18
+ - Being respectful of differing viewpoints and experiences
19
+ - Gracefully accepting constructive criticism
20
+ - Focusing on what is best for the community
21
+ - Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ - The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ - Trolling, insulting/derogatory comments, and personal or political attacks
28
+ - Public or private harassment
29
+ - Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ - Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported
58
+ by contacting a project maintainer. Complaints will result in a response and be
59
+ reviewed and investigated in a way that is deemed necessary and appropriate to the
60
+ circumstances. Maintainers are obligated to maintain confidentiality with regard to the
61
+ reporter of an incident.
62
+
63
+ Project maintainers who do not follow or enforce the Code of Conduct in good
64
+ faith may face temporary or permanent repercussions as determined by other
65
+ members of the project's leadership.
66
+
67
+ ## Attribution
68
+
69
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
70
+ available at [http://contributor-covenant.org/version/1/4][version]
71
+
72
+ [homepage]: http://contributor-covenant.org
73
+ [version]: http://contributor-covenant.org/version/1/4/
package/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright @ 2019 Atlassian Pty Ltd
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
package/README.md ADDED
@@ -0,0 +1,127 @@
1
+ # @atlassian/i18n-properties-loader
2
+
3
+ ![node version](https://img.shields.io/node/v/@atlassian/i18n-properties-loader.svg)
4
+ ![webpack peer dependency version](https://img.shields.io/npm/dependency-version/@atlassian/i18n-properties-loader/peer/webpack.svg)
5
+ ![npm downloads](https://img.shields.io/npm/dt/@atlassian/i18n-properties-loader.svg)
6
+
7
+ A webpack loader for i18n `*.properties` files that can be used in Atlassian Server products and plugins.
8
+
9
+ ## Motivation
10
+
11
+ If your work with the modern Front-End Server code there is a good chance you are already using the
12
+ [Atlassian Web-Resource webpack Plugin](https://www.npmjs.com/package/atlassian-webresource-webpack-plugin).
13
+ If you did configure your webpack to use development server you might be missing displaying translation phrases right
14
+ now.
15
+
16
+ The `@atlassian/i18n-properties-loader` can help you with solving that problem. It's a webpack loader that allows you
17
+ displaying translation phrases during your development workflow and at the same time uses the WRM.
18
+
19
+ For more information about the translations system check the Atlassian Development documentation page:
20
+
21
+ - [Internationalising your plugin](https://developer.atlassian.com/server/framework/atlassian-sdk/internationalising-your-plugin/)
22
+
23
+ ## Installation
24
+
25
+ ```sh
26
+ npm install @atlassian/i18n-properties-loader --save-dev
27
+ ```
28
+
29
+ ## Usage example
30
+
31
+ ```js
32
+ // webpack.config.js
33
+
34
+ const myI18nFiles = [
35
+ 'foo/i18n/my-translation-file.properties',
36
+ 'foo/bar/i18n/my-other-translation-file.properties',
37
+ 'bar/i18n/some-translation-file.properties',
38
+ ];
39
+
40
+ module.exports = {
41
+ module: {
42
+ rules: [
43
+ {
44
+ test: /\.jsx?$/,
45
+ include: ['src'],
46
+
47
+ use: [
48
+ {
49
+ loader: '@atlassian/i18n-properties-loader',
50
+ options: {
51
+ i18nFiles: myI18nFiles,
52
+ },
53
+ },
54
+
55
+ {
56
+ loader: 'babel-loader',
57
+ },
58
+ ],
59
+ },
60
+ ],
61
+ },
62
+ };
63
+ ```
64
+
65
+ ## Options
66
+
67
+ - `i18nFiles` list of paths to your `*.properties` files (required)
68
+ - `disabled` disables the loader; can we used to disabled in production bundle (optional, default `false`)
69
+
70
+ ### Creating production bundle
71
+
72
+ The loader is required only in development mode. You should remember to disable it when you are creaing production bundle.
73
+
74
+ With webpack and its [`mode` configuration](https://webpack.js.org/configuration/mode/) you can intercept the currently selected mode inside your webpack configuration and disable the loader accoridngly:
75
+
76
+ ```js
77
+ // webpack.config.js
78
+
79
+ module.exports = (env, argv) => {
80
+ const isDevelopmentMode = argv.mode === 'development'; // 1. Check if we are running webpack in "development" mode
81
+
82
+ return {
83
+ module: {
84
+ rules: [
85
+ {
86
+ test: /\.jsx?$/,
87
+ include: ['src'],
88
+
89
+ use: [
90
+ {
91
+ loader: '@atlassian/i18n-properties-loader',
92
+ options: {
93
+ i18nFiles,
94
+ disabled: !isDevelopmentMode, // 2. Skip and disable loader when webpack is running in "production" mode
95
+ },
96
+ },
97
+
98
+ {
99
+ loader: 'babel-loader',
100
+ },
101
+ ],
102
+ },
103
+ ],
104
+ },
105
+ };
106
+ };
107
+ ```
108
+
109
+ ## React i18n helper
110
+
111
+ This package plays nice with the [`@atlassian/wrm-react-i18n`](https://www.npmjs.com/package/@atlassian/wrm-react-i18n)
112
+ when you want to use `I18n.getText()` translation helper with React components.
113
+
114
+ You can check the package description for more details and learn how to integrate it with your webpack configuration.
115
+
116
+ ## Additional links
117
+
118
+ - [https://www.npmjs.com/package/@atlassian/i18n-properties-loader](https://www.npmjs.com/package/@atlassian/i18n-properties-loader)
119
+ - [https://www.npmjs.com/package/@atlassian/wrm-react-i18n](https://www.npmjs.com/package/@atlassian/wrm-react-i18n)
120
+ - [https://www.npmjs.com/package/atlassian-webresource-webpack-plugin](https://www.npmjs.com/package/atlassian-webresource-webpack-plugin)
121
+
122
+ ## Minimum requirements
123
+
124
+ This plugin is compatible with:
125
+
126
+ - webpack 4.0+ and 5.0+
127
+ - Node 12+
package/index.js ADDED
@@ -0,0 +1,221 @@
1
+ /* eslint-env node */
2
+ const fs = require('fs');
3
+ const debounce = require('lodash.debounce');
4
+ const { PropertiesFile } = require('java-properties');
5
+ const { getOptions } = require('loader-utils');
6
+ const { validate } = require('schema-utils');
7
+ const rx = require('./rx');
8
+
9
+ const optionsSchema = {
10
+ type: 'object',
11
+ properties: {
12
+ i18nFiles: {
13
+ type: 'array',
14
+ description: 'A list of i18n *.properties files',
15
+ },
16
+
17
+ disabled: {
18
+ type: 'boolean',
19
+ description: 'Should the loader be disabled. By default false',
20
+ default: false,
21
+ },
22
+ },
23
+ additionalProperties: false,
24
+ };
25
+
26
+ // See RegExp in atlassian-plugins-webresource-plugin
27
+ // https://bitbucket.org/atlassian/atlassian-plugins-webresource/src/master/atlassian-plugins-webresource-plugin/src/main/java/com/atlassian/webresource/plugin/i18n/JsI18nTransformer.java#lines-48:63
28
+ const i18nRegExp = rx('g')`
29
+ (?:
30
+ # Optional module identifier
31
+ (?:
32
+ # Optional namespace identifier
33
+
34
+ (?<namespace>
35
+ # "identifiers can contain only alphanumeric characters (or "$" or "_"), and may not start
36
+ # with a digit" https://developer.mozilla.org/en-US/docs/Glossary/Identifier
37
+ (?:[A-Za-z$_][0-9A-Za-z$_]{0,1000})?
38
+
39
+ # optional ["default"] or ['default'] for babel 5, see PLUGWEB-306
40
+ (?:\[["']default["']])?
41
+
42
+ # optional .default for babel 6
43
+ (?:\.default)?
44
+
45
+ ) # end namespace identifier
46
+
47
+ # Babel 6 and Babel 7 + Webpack 4
48
+ (?:\.I18n|\[['"]I18n['"]])
49
+
50
+ ) # end optional module identifier
51
+
52
+ # A call without a module identifier with a required word boundary
53
+ |(?:\bI18n)
54
+ )
55
+
56
+ # call to getText function
57
+ \.getText
58
+
59
+ # start parenthesis
60
+ \(\s*
61
+
62
+ # single or double quote world
63
+ ["'](?<key>[\w\.\-\s]+)["']
64
+
65
+ # end parenthesis, or start-of-args
66
+ \s*(?<endParam>[,|\)])
67
+ `;
68
+
69
+ const namedEsmImportRegexp = rx('gm')`
70
+ ^\s? # possible white-spaces at the beginning
71
+
72
+ import\s+
73
+
74
+ \{\s*I18n\s*\}\s+ # The named ESM import
75
+
76
+ from\s+
77
+ ['"\`]
78
+
79
+ (?<module> # List of supported modules
80
+ (?:
81
+ # NPM package "@atlassian/wrm-react-i18n"
82
+ @atlassian\/wrm-react-i18n
83
+ |
84
+ # Built-in WRM module
85
+ wrm\/i18n
86
+ )
87
+ )
88
+ ['"\`]
89
+ `;
90
+
91
+ let i18nCache = new Map();
92
+
93
+ // small enough that i18n file changes are propagated. Large enough for cache hits.
94
+ const accessThreshold = 1000;
95
+
96
+ const clearCacheWhenIdle = debounce(() => {
97
+ i18nCache = new Map();
98
+ }, accessThreshold);
99
+
100
+ function processI18nFiles(i18nFiles) {
101
+ clearCacheWhenIdle();
102
+
103
+ if (i18nCache.has(i18nFiles)) {
104
+ return i18nCache.get(i18nFiles);
105
+ }
106
+
107
+ const missingFiles = i18nFiles.filter((file) => !fs.existsSync(file) || !fs.statSync(file).isFile());
108
+
109
+ if (missingFiles.length) {
110
+ const err = new Error('I18n Loader: i18n files are missing\n\t' + missingFiles.join('\n\t'));
111
+ err.missingFiles = missingFiles;
112
+
113
+ throw err;
114
+ }
115
+
116
+ const properties = new PropertiesFile();
117
+ i18nFiles.forEach((file) => properties.addFile(file));
118
+
119
+ i18nCache.set(i18nFiles, properties);
120
+
121
+ return properties;
122
+ }
123
+
124
+ module.exports = function (source, map) {
125
+ const options = getOptions(this);
126
+ validate(optionsSchema, options, { name: 'i18n-properties-loader' });
127
+
128
+ const { i18nFiles = [], disabled = false } = options;
129
+
130
+ // Skip loader when e.g. we are not running webpack in dev mode
131
+ if (disabled) {
132
+ return this.callback(null, source, map);
133
+ }
134
+
135
+ i18nFiles.forEach((file) => this.addDependency(file));
136
+
137
+ const callback = this.async();
138
+
139
+ const isNamedEsmImport = Boolean(source.match(namedEsmImportRegexp));
140
+
141
+ try {
142
+ let esmFormatFunctionName = 'format';
143
+
144
+ // Replace the named ESM import of "getText" call to "format"
145
+ if (isNamedEsmImport) {
146
+ esmFormatFunctionName = '__format__';
147
+
148
+ source = source.replace(namedEsmImportRegexp, (match, module) => {
149
+ return `\nimport { format as ${esmFormatFunctionName} } from "${module}"`;
150
+ });
151
+ }
152
+
153
+ // Replace "I18n.getText('some.translation.key', [param1], [paramN])" with the real translation string
154
+ const properties = processI18nFiles(i18nFiles);
155
+ const newSource = source.replace(i18nRegExp, (...args) => {
156
+ const { namespace, key, endParam } = args.pop();
157
+ const escapedKey = key.replace(/\s/g, '\\ ');
158
+
159
+ let message = properties.get(escapedKey);
160
+
161
+ if (message === undefined) {
162
+ this.emitWarning(`I18n Loader: Can not find "${key}" phrase ID in your *.properties files`);
163
+
164
+ // Fallback to value of "key" so we can avoid breaking JavaScript syntax when
165
+ // we have additional parameters we need to substitute
166
+ message = key;
167
+ }
168
+
169
+ const formatFunctionCall = isNamedEsmImport ? esmFormatFunctionName : `${namespace}.format`;
170
+
171
+ // Output string
172
+ const escapedMessage = JSON.stringify(message);
173
+
174
+ if (endParam === ',') {
175
+ // We don't need to unquote the string since the WRM.format function has all the logic to do that
176
+ return `${formatFunctionCall}(${escapedMessage},`;
177
+ }
178
+
179
+ return unquoteMessage(escapedMessage);
180
+ });
181
+
182
+ callback(null, newSource, map);
183
+ } catch (error) {
184
+ if (error.missingFiles) {
185
+ error.missingFiles.forEach((file) => this.emitError(`I18n Loader: File ${file} does not exists`));
186
+ } else {
187
+ this.emitError(error);
188
+ }
189
+
190
+ callback(error);
191
+ }
192
+ };
193
+
194
+ // https://docs.oracle.com/javase/8/docs/api/java/text/MessageFormat.html
195
+ function unquoteMessage(input) {
196
+ const match = input.match(/'/g);
197
+
198
+ if (!match) {
199
+ return input;
200
+ }
201
+ // Edge-cases: If there is an only single quote character this means that the message is misformatted.
202
+ // The ' char should be used in pairs to quote values.
203
+ if (match.length === 1) {
204
+ return input.replace("'", '');
205
+ }
206
+
207
+ input = input
208
+ // Unquote any quoted values
209
+ // Within a String, a pair of single quotes can be used to quote any arbitrary characters except single quotes.
210
+ .replace(/'([^']+)'/g, '$1')
211
+
212
+ // Unquote remaining single quotes
213
+ // A single quote itself must be represented by doubled single quotes '' throughout a String
214
+ .replace("''", "'");
215
+
216
+ return input;
217
+ }
218
+
219
+ /** @visibleForTesting */
220
+ module.exports._i18nRegExp = i18nRegExp;
221
+ module.exports._namedEsmImportRegexp = namedEsmImportRegexp;
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@atlassian/i18n-properties-loader",
3
+ "version": "0.0.0-snapshot.0",
4
+ "description": "A webpack loader for i18n *.properties files that can be used in Atlassian Server products",
5
+ "main": "index.js",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+ssh://git@bitbucket.org/atlassianlabs/fe-server.git",
9
+ "directory": "packages/i18n-properties-loader"
10
+ },
11
+ "publishConfig": {
12
+ "registry": "https://registry.npmjs.org/"
13
+ },
14
+ "scripts": {
15
+ "test": "jest --verbose",
16
+ "test:watch": "jest --watch --verbose",
17
+ "test:ci": "jest --ci --silent=false"
18
+ },
19
+ "keywords": [
20
+ "react",
21
+ "i18n",
22
+ "frontend",
23
+ "server",
24
+ "atlassian",
25
+ "dc",
26
+ "front-end",
27
+ "bitbucket",
28
+ "jira",
29
+ "confluence",
30
+ "jsd",
31
+ "webpack",
32
+ "loader",
33
+ "wrm"
34
+ ],
35
+ "author": "Atlassian Pty Ltd.",
36
+ "license": "Apache-2.0",
37
+ "homepage": "https://bitbucket.org/atlassianlabs/fe-server",
38
+ "bugs": "https://ecosystem.atlassian.net/jira/software/c/projects/SPFE/issues/",
39
+ "dependencies": {
40
+ "java-properties": "^1.0.2",
41
+ "loader-utils": "2.0.4",
42
+ "lodash.debounce": "^4.0.8",
43
+ "schema-utils": "^3.0.0"
44
+ },
45
+ "peerDependencies": {
46
+ "webpack": "^5.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "atlassian-webresource-webpack-plugin": "^0.0.0-snapshot.0",
50
+ "jest": "27.4.3",
51
+ "webpack": "5.90.3"
52
+ },
53
+ "engines": {
54
+ "node": ">=12"
55
+ },
56
+ "gitHead": "c201fc7caf8aeb31df5cfcc4757f129b922d1ea9"
57
+ }
package/rx.js ADDED
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Creates new regex.
3
+ * Source: https://gist.github.com/shannonmoeller/b4f6fbab2ffec56213e7
4
+ *
5
+ * @param flags
6
+ * @return {RegExp}
7
+ */
8
+ module.exports = function rx(flags) {
9
+ const trailingComments = /\s+#.*$/gm;
10
+ const surroundingWhitespace = /^\s+|\s+$/gm;
11
+ const literalNewlines = /[\r\n]/g;
12
+
13
+ return (strings, ...values) => {
14
+ function toPattern(pattern, rawString, i) {
15
+ let value = values[i];
16
+
17
+ if (value == null) {
18
+ return pattern + rawString;
19
+ }
20
+
21
+ if (value instanceof RegExp) {
22
+ value = value.source;
23
+ }
24
+
25
+ return pattern + rawString + value;
26
+ }
27
+
28
+ const compiledPattern = strings.raw
29
+ .reduce(toPattern, '')
30
+ .replace(trailingComments, '')
31
+ .replace(surroundingWhitespace, '')
32
+ .replace(literalNewlines, '');
33
+
34
+ return new RegExp(compiledPattern, flags);
35
+ };
36
+ };