SPA: 4. Lokalisation
Lokalisation mit AngularJS
Um die Webseite in mehreren Sprachen anzubieten und Textinhalte sauber vom Quellcode zu trennen, gibt es mehrere Lösungen für AngularJS. Ich habe ein eigenes Modul entwickelt, um das Ändern einer Sprache ohne das erneute Laden der Seite zu ermöglichen.
Das Projekt ist auf GitHub verfügbar.
https://github.com/bajak/AngularJS-Localization
Die Bibliothek ist von jQuery abhängig.
http://jquery.com/download/
Wir erstellen die Dateien…
~/Scripts/app/config/localize.js
In dieser Datei konfigurieren wir die verfügbaren Sprachen und initialisieren das Modul.
app.config(["localizeProvider", function (localizeProvider) {
localizeProvider.setDefaultLanguage("en-EN");
localizeProvider.addLanguage("en-EN");
localizeProvider.addLanguage("de-DE");
localizeProvider.addDefaultUrl(
"en-EN", "./Content/Text/index-en-EN.lang");
localizeProvider.addDefaultUrl(
"de-DE", "./Content/Text/index-de-DE.lang");
}]);app.run(["localize", function(localize) {
localize.initialize();
}
]);~/Content/text/index-de-DE.lang
Die Sprachdatei für die Hauptansicht. Zeilenumbrüche innerhalb eines Wertes sind erlaubt, Schachtelungen jedoch nicht. Den RouteScope weisen wir mit einem $ Zeichen vor dem Schlüssel zu. Attribute können innerhalb des Schlüssels mit /[Attributname/] zugewiesen werden.
"$index.metaTitle" : "SPA Meta Title DE",
"$index.metaDescription" : "SPA Meta Description DE",
".lang-label": "Sprache : ",
"#lang-de" : "DE",
"#lang-en" : "EN",
".menu > p" : "Ansichten: ",
".menu > a[href='/Start']" : "Start",
".menu > a[href='/User']" : "Benutzer",
".menu > a[href='/About']" : "Über mich"
und so weiter…
Wir ändern die Dateien…
~/Scripts/app/config/router.js
Hier verweisen wir auf die Sprachdateien zu unseren Ansichten. Dazu verwenden wir eine zusätzliche Eigenschaft localizeUrl. Diese enhält die Sprache als Schlüssel, den Verweis als Wert.
app.config(["$routeProvider", "$locationProvider", "$provide",
function ($routeProvider, $locationProvider, $provide) {
$routeProvider.when("/Start", {
templateUrl: "./Views/start.html",
controller: "StartCtrl",
localizeUrl: {
"en-EN": "./Content/Text/start-en-EN.lang",
"de-DE": "./Content/Text/start-de-DE.lang"
}}).when("/About", {
templateUrl: "./Views/about.html",
controller: "AboutCtrl",
localizeUrl: {
"en-EN": "./Content/Text/about-en-EN.lang",
"de-DE": "./Content/Text/about-de-DE.lang"
}}).otherwise({
redirectTo: "/Start"
});
$provide.decorator("$sniffer", ["$delegate", function($delegate) {
if(!window.history && !window.history.pushState)
$delegate.history = false;
return $delegate;
}]);
$locationProvider.hashPrefix("!");
$locationProvider.html5Mode(true);
}]);
~/Scripts/app/views/index.js
Aus dem RouteScope kopieren wir das Index-Objekt in den lokalen Scope. Ausserdem stellen wir eine Funktion zum Sprachwechsel bereit.
app.controller("IndexCtrl", ["$scope", "localize",
function ($scope, localize) {
$scope.index = $rootScope.index;
$scope.changeLanguage = localize.changeLanguage;
}]);~/Scripts/app/app.js
Die Applikation muss um unser Modul erweitert werden.
var app = angular.module("app", ["localization", "ngRoute",
"ngSanitize", "ngAnimate", "ngCookies", "ngResource"]);angular.element(document).ready(function() {
var html = document.getElementsByTagName("html")[0];
angular.bootstrap(html, ["app"]);
});~/Views/index.cshtml
Die Hauptansicht enthält keine Texte. Diese Aufgabe kann jetzt unsere Konfiguration übernehmen.
@inherits System.Web.Mvc.WebViewPage
@using System.Web.Optimization
<!doctype html>
<html lang=”en” ng-controller=”IndexCtrl”>
<head>
<meta charset=”UTF-8" />
<meta http-equiv=”X-UA-Compatible” content=”IE=10" />
<meta name=”title” content=”{{index.metaTitle}}”>
<meta name=”description” content=”{{index.metaDescription}}”/>
<title ng-bind=”index.metaTitle”></title>
@Styles.Render(“~/content/styles/css”)
@Scripts.Render(“~/scripts/app/bundle”)
</head>
<body>
<p class=”lang-label”></p>
<a id=”lang-de” href=”” ng-click=”changeLanguage(‘de-de’)”></a>
<a id=”lang-en” href=”” ng-click=”changeLanguage(‘en-en’)”></a>
<br/>
<div class=”menu”>
<p></p>
<a href=”/Start”></a>
<a href=”/About”></a>
</div>
<div id=”page” class=”toggle” ng-view></div>
</body>
</html>
~/App_Start/BundleConfig.cs
Wir ergänzen die BundleConfig mit allen neuen Dateien.
public static void RegisterBundles(BundleCollection bundles){
bundles.Add(new StyleBundle("~/Content/Styles/css")
.Include("~/Content/Styles/style.css")); bundles.Add(new ScriptBundle("~/Scripts/bundle")
.Include("~/Scripts/libs/jquery-2.0.3.js")
.Include("~/Scripts/libs/angular.js")
.Include("~/Scripts/libs/angular-cookies.js")
.Include("~/Scripts/libs/angular-sanitize.js")
.Include("~/Scripts/libs/angular-animate.js")
.Include("~/Scripts/libs/angular-route.js")
.Include("~/Scripts/libs/angular-resource.js")
.Include("~/Scripts/libs/angular-localize.js")
.Include("~/Scripts/app/app.js")
.Include("~/Scripts/app/config/router.js")
.Include("~/Scripts/app/config/localize.js")
.Include("~/Scripts/app/controller/index.js")
.Include("~/Scripts/app/controller/start.js")
.Include("~/Scripts/app/controller/about.js"));
}
}