mirror of
https://github.com/bitwarden/browser
synced 2026-02-06 11:43:51 +00:00
Merge branch 'arch/ng-localize' into kiro-localize
# Conflicts: # apps/browser/src/autofill/notification/bar.ts # apps/browser/webpack.config.js # package-lock.json # package.json
This commit is contained in:
11
angular.json
11
angular.json
@@ -44,8 +44,11 @@
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"builder": "@angular-builders/custom-webpack:browser",
|
||||
"options": {
|
||||
"customWebpackConfig": {
|
||||
"path": "./apps/web/webpack.i18n.js"
|
||||
},
|
||||
"outputPath": "dist/web",
|
||||
"index": "apps/web/src/index.html",
|
||||
"main": "apps/web/src/main.ts",
|
||||
@@ -55,6 +58,12 @@
|
||||
"styles": [],
|
||||
"scripts": []
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-builders/custom-webpack:extract-i18n",
|
||||
"options": {
|
||||
"buildTarget": "web:build"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
11
apps/browser/src/_locales/messages.sv-se.json
Normal file
11
apps/browser/src/_locales/messages.sv-se.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"locale": "sv-Se",
|
||||
"translations": {
|
||||
"4606963464835766483": "Uppdaterad {$ICU}",
|
||||
"2002272803511843863": "{VAR_PLURAL, plural, =0 {precis nu} =1 {en minut sedan} other {för {INTERPOLATION} minuter sedan}}",
|
||||
"1150463724722084961": "Detta är en flytande länk till {$START_LINK}Inställningar{$CLOSE_LINK} med text före och efter.",
|
||||
"5010897546053474360": "En fras som vi verkligen {$START_TAG_STRONG}behöver{$CLOSE_TAG_STRONG} framhäva!",
|
||||
"email": "E-postadress",
|
||||
"616177228530588915": "En översatt sträng med en länk. {$PH}"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
import "@angular/localize/init";
|
||||
import { loadTranslations } from "@angular/localize";
|
||||
import { render } from "lit";
|
||||
|
||||
import { Theme, ThemeTypes } from "@bitwarden/common/platform/enums";
|
||||
@@ -23,6 +25,19 @@ import {
|
||||
NotificationTypes,
|
||||
} from "./abstractions/notification-bar";
|
||||
|
||||
async function initLanguage(locale: string): Promise<void> {
|
||||
if (locale === "en") {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = await fetch("/_locales/messages." + locale + ".json").then((r) => r.json());
|
||||
|
||||
loadTranslations(json.translations);
|
||||
$localize.locale = locale;
|
||||
}
|
||||
|
||||
void initLanguage("sv-se");
|
||||
|
||||
const logService = new ConsoleLogService(false);
|
||||
let notificationBarIframeInitData: NotificationBarIframeInitData = {};
|
||||
let windowMessageOrigin: string;
|
||||
@@ -55,6 +70,7 @@ function applyNotificationBarStyle() {
|
||||
}
|
||||
|
||||
function getI18n() {
|
||||
const a = 5;
|
||||
return {
|
||||
appName: chrome.i18n.getMessage("appName"),
|
||||
atRiskPassword: chrome.i18n.getMessage("atRiskPassword"),
|
||||
@@ -219,7 +235,7 @@ export function getNotificationTestId(
|
||||
function setElementText(template: HTMLTemplateElement, elementId: string, text: string): void {
|
||||
const element = template.content.getElementById(elementId);
|
||||
if (element) {
|
||||
element.textContent = text;
|
||||
element.innerHTML = text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { enableProdMode } from "@angular/core";
|
||||
import { loadTranslations } from "@angular/localize";
|
||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||
|
||||
import { PopupSizeService } from "../platform/popup/layout/popup-size.service";
|
||||
@@ -22,8 +23,17 @@ if (process.env.ENV === "production") {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
function init() {
|
||||
void platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
}
|
||||
void initLanguage("sv-se").then(() => {
|
||||
return platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
});
|
||||
|
||||
init();
|
||||
async function initLanguage(locale: string): Promise<void> {
|
||||
if (locale === "en") {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = await fetch("/_locales/messages." + locale + ".json").then((r) => r.json());
|
||||
|
||||
loadTranslations(json.translations);
|
||||
$localize.locale = locale;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import "core-js/stable";
|
||||
import "core-js/proposals/explicit-resource-management";
|
||||
import "zone.js";
|
||||
import "@angular/localize/init";
|
||||
|
||||
@@ -81,7 +81,7 @@ const moduleRules = [
|
||||
{
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
configFile: "../../babel.config.json",
|
||||
configFile: "../../babel2.config.json",
|
||||
cacheDirectory: ENV === "development",
|
||||
compact: ENV !== "development",
|
||||
},
|
||||
|
||||
@@ -13,15 +13,7 @@ export class I18nService extends BaseI18nService {
|
||||
systemLanguage || "en-US",
|
||||
localesDirectory,
|
||||
async (formattedLocale: string) => {
|
||||
const filePath =
|
||||
this.localesDirectory +
|
||||
"/" +
|
||||
formattedLocale +
|
||||
"/messages.json?cache=" +
|
||||
process.env.CACHE_TAG;
|
||||
const localesResult = await fetch(filePath);
|
||||
const locales = await localesResult.json();
|
||||
return locales;
|
||||
return Promise.resolve({});
|
||||
},
|
||||
globalStateProvider,
|
||||
);
|
||||
|
||||
10
apps/web/src/locales/messages.sv-se.json
Normal file
10
apps/web/src/locales/messages.sv-se.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"locale": "sv-Se",
|
||||
"translations": {
|
||||
"4606963464835766483": "Uppdaterad {$ICU}",
|
||||
"2002272803511843863": "{VAR_PLURAL, plural, =0 {precis nu} =1 {en minut sedan} other {för {INTERPOLATION} minuter sedan}}",
|
||||
"1150463724722084961": "Detta är en flytande länk till {$START_LINK}Inställningar{$CLOSE_LINK} med text före och efter.",
|
||||
"5010897546053474360": "En fras som vi verkligen {$START_TAG_STRONG}behöver{$CLOSE_TAG_STRONG} framhäva!",
|
||||
"email": "E-postadress"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { enableProdMode } from "@angular/core";
|
||||
import { loadTranslations } from "@angular/localize";
|
||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||
|
||||
import { AppModule } from "./app/app.module";
|
||||
@@ -7,4 +8,17 @@ if (process.env.NODE_ENV === "production") {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
void platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
void initLanguage("sv-se").then(() => {
|
||||
return platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
});
|
||||
|
||||
async function initLanguage(locale: string): Promise<void> {
|
||||
if (locale === "en") {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = await fetch("/locales/messages." + locale + ".json").then((r) => r.json());
|
||||
|
||||
loadTranslations(json);
|
||||
$localize.locale = locale;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import "core-js/stable";
|
||||
import "core-js/proposals/explicit-resource-management";
|
||||
import "zone.js";
|
||||
|
||||
import "@angular/localize/init";
|
||||
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
// Production
|
||||
} else {
|
||||
|
||||
@@ -80,7 +80,7 @@ const moduleRules = [
|
||||
{
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
configFile: "../../babel.config.json",
|
||||
configFile: "../../babel2.config.json",
|
||||
cacheDirectory: NODE_ENV !== "production",
|
||||
},
|
||||
},
|
||||
|
||||
218
apps/web/webpack.i18n.js
Normal file
218
apps/web/webpack.i18n.js
Normal file
@@ -0,0 +1,218 @@
|
||||
const path = require("path");
|
||||
|
||||
const { AngularWebpackPlugin } = require("@ngtools/webpack");
|
||||
const CopyWebpackPlugin = require("copy-webpack-plugin");
|
||||
const HtmlWebpackInjector = require("html-webpack-injector");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const webpack = require("webpack");
|
||||
|
||||
const config = require("./config.js");
|
||||
const pjson = require("./package.json");
|
||||
|
||||
const ENV = process.env.ENV == null ? "development" : process.env.ENV;
|
||||
const NODE_ENV = process.env.NODE_ENV == null ? "development" : process.env.NODE_ENV;
|
||||
const LOGGING = process.env.LOGGING != "false";
|
||||
|
||||
const envConfig = config.load(ENV);
|
||||
if (LOGGING) {
|
||||
config.log(envConfig);
|
||||
}
|
||||
|
||||
const moduleRules = [
|
||||
{
|
||||
test: /\.(html)$/,
|
||||
loader: "html-loader",
|
||||
},
|
||||
{
|
||||
test: /.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
|
||||
exclude: /loading(|-white).svg/,
|
||||
generator: {
|
||||
filename: "fonts/[name].[contenthash][ext]",
|
||||
},
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.(jpe?g|png|gif|svg|webp|avif)$/i,
|
||||
exclude: /.*(bwi-font)\.svg/,
|
||||
generator: {
|
||||
filename: "images/[name][ext]",
|
||||
},
|
||||
type: "asset/resource",
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
},
|
||||
"css-loader",
|
||||
"resolve-url-loader",
|
||||
{
|
||||
loader: "sass-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{
|
||||
loader: MiniCssExtractPlugin.loader,
|
||||
},
|
||||
"css-loader",
|
||||
"resolve-url-loader",
|
||||
{
|
||||
loader: "postcss-loader",
|
||||
options: {
|
||||
sourceMap: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
test: /\.[jt]sx?$/,
|
||||
use: [
|
||||
{
|
||||
loader: "@ngtools/webpack",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /argon2(-simd)?\.wasm$/,
|
||||
loader: "base64-loader",
|
||||
type: "javascript/auto",
|
||||
},
|
||||
];
|
||||
|
||||
const plugins = [
|
||||
new HtmlWebpackPlugin({
|
||||
template: "./apps/web/src/index.html",
|
||||
filename: "index.html",
|
||||
chunks: ["theme_head", "app/polyfills", "app/vendor", "app/main", "styles"],
|
||||
}),
|
||||
new HtmlWebpackInjector(),
|
||||
new HtmlWebpackPlugin({
|
||||
template: "./apps/web/src/404.html",
|
||||
filename: "404.html",
|
||||
chunks: ["styles"],
|
||||
// 404 page is a wildcard, this ensures it uses absolute paths.
|
||||
publicPath: "/",
|
||||
}),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{ from: "./apps/web/src/.nojekyll" },
|
||||
{ from: "./apps/web/src/manifest.json" },
|
||||
{ from: "./apps/web/src/favicon.ico" },
|
||||
{ from: "./apps/web/src/browserconfig.xml" },
|
||||
{ from: "./apps/web/src/app-id.json" },
|
||||
{ from: "./apps/web/src/images", to: "images" },
|
||||
{ from: "./apps/web/src/locales", to: "locales" },
|
||||
{ from: "./node_modules/qrious/dist/qrious.min.js", to: "scripts" },
|
||||
{ from: "./node_modules/braintree-web-drop-in/dist/browser/dropin.js", to: "scripts" },
|
||||
{
|
||||
from: "./apps/web/src/version.json",
|
||||
transform(content, path) {
|
||||
return content.toString().replace("process.env.APPLICATION_VERSION", pjson.version);
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: "[name].[contenthash].css",
|
||||
chunkFilename: "[id].[contenthash].css",
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
process: "process/browser.js",
|
||||
}),
|
||||
new webpack.EnvironmentPlugin({
|
||||
ENV: ENV,
|
||||
NODE_ENV: NODE_ENV === "production" ? "production" : "development",
|
||||
APPLICATION_VERSION: pjson.version,
|
||||
CACHE_TAG: Math.random().toString(36).substring(7),
|
||||
URLS: envConfig["urls"] ?? {},
|
||||
STRIPE_KEY: envConfig["stripeKey"] ?? "",
|
||||
BRAINTREE_KEY: envConfig["braintreeKey"] ?? "",
|
||||
PAYPAL_CONFIG: envConfig["paypal"] ?? {},
|
||||
FLAGS: envConfig["flags"] ?? {},
|
||||
DEV_FLAGS: NODE_ENV === "development" ? envConfig["devFlags"] : {},
|
||||
ADDITIONAL_REGIONS: envConfig["additionalRegions"] ?? [],
|
||||
}),
|
||||
new AngularWebpackPlugin({
|
||||
tsconfig: "apps/web/tsconfig.build.json",
|
||||
entryModule: "src/app/app.module#AppModule",
|
||||
sourceMap: true,
|
||||
}),
|
||||
];
|
||||
|
||||
const webpackConfig = {
|
||||
mode: NODE_ENV,
|
||||
devtool: "source-map",
|
||||
target: "web",
|
||||
entry: {
|
||||
"app/polyfills": "./apps/web/src/polyfills.ts",
|
||||
"app/main": "./apps/web/src/main.ts",
|
||||
styles: ["./apps/web/src/scss/styles.scss", "./apps/web/src/scss/tailwind.css"],
|
||||
theme_head: "./apps/web/src/theme.ts",
|
||||
},
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
commons: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: "app/vendor",
|
||||
chunks: (chunk) => {
|
||||
return chunk.name === "app/main";
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
terserOptions: {
|
||||
safari10: true,
|
||||
// Replicate Angular CLI behaviour
|
||||
compress: {
|
||||
global_defs: {
|
||||
ngDevMode: false,
|
||||
ngI18nClosureMode: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".js"],
|
||||
symlinks: false,
|
||||
modules: [path.resolve("../../node_modules")],
|
||||
fallback: {
|
||||
buffer: false,
|
||||
util: require.resolve("util/"),
|
||||
assert: false,
|
||||
url: false,
|
||||
fs: false,
|
||||
process: false,
|
||||
path: require.resolve("path-browserify"),
|
||||
},
|
||||
},
|
||||
output: {
|
||||
filename: "[name].[contenthash].js",
|
||||
path: path.resolve(__dirname, "build"),
|
||||
clean: true,
|
||||
},
|
||||
module: {
|
||||
noParse: /argon2(-simd)?\.wasm$/,
|
||||
rules: moduleRules,
|
||||
},
|
||||
experiments: {
|
||||
asyncWebAssembly: true,
|
||||
},
|
||||
plugins: plugins,
|
||||
};
|
||||
|
||||
module.exports = webpackConfig;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { enableProdMode } from "@angular/core";
|
||||
import { loadTranslations } from "@angular/localize";
|
||||
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
|
||||
|
||||
import { AppModule } from "./app/app.module";
|
||||
@@ -7,4 +8,17 @@ if (process.env.NODE_ENV === "production") {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
void platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
void initLanguage("sv-se").then(() => {
|
||||
return platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
});
|
||||
|
||||
async function initLanguage(locale: string): Promise<void> {
|
||||
if (locale === "en") {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = await fetch("/locales/messages." + locale + ".json").then((r) => r.json());
|
||||
|
||||
loadTranslations(json.translations);
|
||||
$localize.locale = locale;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!--
|
||||
<!--
|
||||
# Table of Contents
|
||||
|
||||
This file contains a single consolidated template for all visual clients.
|
||||
@@ -10,6 +10,12 @@
|
||||
MASTER_PASSWORD_ENTRY: displays the master password input field + login button
|
||||
-->
|
||||
|
||||
<p i18n>Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {{{ 5 }} minutes ago}}</p>
|
||||
|
||||
<p i18n>This is a inline link to <a href="/settings">Settings</a> with text before and after.</p>
|
||||
|
||||
<p i18n>A phrase we really <strong>need</strong> to highlight!</p>
|
||||
|
||||
<form [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<div [ngClass]="{ 'tw-hidden': loginUiState !== LoginUiState.EMAIL_ENTRY }">
|
||||
<!-- Email Address input -->
|
||||
|
||||
@@ -77,6 +77,7 @@ export class LoginComponent implements OnInit, OnDestroy {
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
readonly Icons = { WaveIcon, VaultIcon };
|
||||
protected minutes = 5;
|
||||
|
||||
clientType: ClientType;
|
||||
ClientType = ClientType;
|
||||
|
||||
888
package-lock.json
generated
888
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,7 @@
|
||||
"@angular-eslint/schematics": "19.6.0",
|
||||
"@angular/cli": "19.2.14",
|
||||
"@angular/compiler-cli": "19.2.14",
|
||||
"@angular/localize": "19.2.14",
|
||||
"@babel/core": "7.24.9",
|
||||
"@babel/preset-env": "7.24.8",
|
||||
"@compodoc/compodoc": "1.1.26",
|
||||
@@ -155,6 +156,7 @@
|
||||
"webpack-node-externals": "3.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-builders/custom-webpack": "19.0.1",
|
||||
"@angular/animations": "19.2.14",
|
||||
"@angular/cdk": "19.2.18",
|
||||
"@angular/common": "19.2.14",
|
||||
|
||||
Reference in New Issue
Block a user