Browse Source

Docs for i18n

dereuromark 9 years ago
parent
commit
95c6a9eea6
2 changed files with 91 additions and 1 deletions
  1. 69 0
      docs/I18n/I18n.md
  2. 22 1
      src/Utility/Language.php

+ 69 - 0
docs/I18n/I18n.md

@@ -0,0 +1,69 @@
+# I18n
+
+Internationalization is always tricky as it involves several layers,
+from routing to controller logic and view outputs to URL building and redirecting.
+
+## Session based language switch
+To detect and switch based on language, you can leverage the Language class.
+Either you manually use `findMatches()` to sort through, or you use the convenience method `findFirstMatch()`:
+```php
+	/**
+	 * @return void
+	 */
+	public function initialize() {
+		parent::initialize();
+
+		// First check the session
+		$language = $this->request->session()->read('Config.language');
+		// Then check the browser preference for the whitelisted languages
+		if (!$language) {
+			$language = Language::findFirstMatch(['de', 'en']);
+		}
+		// Overwrite the system default
+		if ($language) {
+			Configure::write('Config.language', substr($language, 0, 2));
+			I18n::locale($language);
+		}
+```
+
+You then just need a switch on the website that allows the other to change the language (by writing it into the session):
+```php
+<?php if (Configure::read('Config.language') === 'de') {
+	echo $this->Html->image('flag_de.png', ['title' => __('German')]);
+} else {
+	echo $this->Form->postLink($this->Html->image('flag_de.png'), ['prefix' => false, 'plugin' => 'Tools', 'controller' => 'ShuntRequest', 'action' => 'language', 'de'], ['block' => true, 'escape' => false, 'title' => __('German')]);
+} ?>
+<?php if (Configure::read('Config.language') === 'en') {
+	echo $this->Html->image('flag_en.png', ['title' => __('English')]);
+} else {
+	echo $this->Form->postLink($this->Html->image('flag_en.png'), ['prefix' => false, 'plugin' => 'Tools', 'controller' => 'ShuntRequest', 'action' => 'language', 'en'], ['block' => true, 'escape' => false, 'title' => __('English')]);
+}?>
+```
+
+Make sure you included the routes for the Tools plugin for this to work or set them up manually in the `src/Config/routes.php` file.
+
+
+## Using language in URLs
+Instead of the "easy" session-based way you might want to use URLs like `domain.tld/en/controller/action` instead. 
+ 
+Switch out the above session check then with
+```php
+if (!$language) {
+	$language = $this->request->getParam('language');
+}
+```
+
+And make sure your routes are all adjusted to accept and parse the language param:
+```php 
+Router::scope('/', function (RouteBuilder $routes) {
+	$routes->connect('/', ['controller' => 'Pages', 'action' => 'display', 'home']);
+
+	$routes->connect(
+		'/:language/:controller/:action/*',
+		[],
+		['language' => 'en']
+	);
+	
+	...
+}
+```

+ 22 - 1
src/Utility/Language.php

@@ -3,7 +3,7 @@
 namespace Tools\Utility;
 
 /**
- * @deprecated ? Should be in the core now
+ * Parses Browser detected preferred language.
  */
 class Language {
 
@@ -46,6 +46,27 @@ class Language {
 	 *
 	 * @param array $accepted
 	 * @param array $available
+	 * @return string|null
+	 */
+	public static function findFirstMatch(array $accepted, array $available = []) {
+		$matches = static::findMatches($accepted, $available);
+		if (!$matches) {
+			return null;
+		}
+
+		$match = array_shift($matches);
+		if (!$match) {
+			return null;
+		}
+
+		return array_shift($match);
+	}
+
+	/**
+	 * Compares two parsed arrays of language tags and find the matches
+	 *
+	 * @param array $accepted
+	 * @param array $available
 	 * @return array
 	 */
 	public static function findMatches(array $accepted, array $available = []) {