commit 4f2db3a0b50fbf8cfd20b17e35094d380a9332dd
Author: Bart Feenstra <bart@mynameisbart.com>
Date:   Fri Feb 14 00:23:45 2014 +0100

    foo

diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php
index f1a1cbe..b23b556 100644
--- a/core/lib/Drupal/Core/Language/Language.php
+++ b/core/lib/Drupal/Core/Language/Language.php
@@ -10,13 +10,9 @@
 /**
  * An object containing the information for an interface language.
  *
- * @todo To keep backwards compatibility with stdClass, we currently use
- * public scopes for the Language class's variables. We will change these to
- * full get/set functions in a follow-up issue: http://drupal.org/node/1512424
- *
  * @see language_default()
  */
-class Language {
+class Language implements LanguageInterface {
 
   /**
    * The values to use to instantiate the default language.
@@ -51,11 +47,11 @@ class Language {
   /**
    * The direction, left-to-right, or right-to-left.
    *
-   * Defined using constants, either DIRECTION_LTR or const DIRECTION_RTL.
+   * Defined using constants, either self::DIRECTION_LTR or self::DIRECTION_RTL.
    *
    * @var int
    */
-  public $direction = Language::DIRECTION_LTR;
+  public $direction = self::DIRECTION_LTR;
 
   /**
    * The weight, used for ordering languages in lists, like selects or tables.
@@ -74,11 +70,14 @@ class Language {
   /**
    * The language negotiation method used when a language was detected.
    *
-   * @var bool
+   * The method ID, for example
+   * \Drupal\language\LanguageNegotiatorInterface::METHOD_ID.
+   *
+   * @var string
    *
    * @see language_types_initialize()
    */
-  public $method_id = NULL;
+  public $method_id;
 
   /**
    * Locked indicates a language used by the system, not an actual language.
@@ -92,112 +91,124 @@ class Language {
   public $locked = FALSE;
 
   /**
-   * Special system language code (only applicable to UI language).
+   * Builds the default language object.
    *
-   * Refers to the language used in Drupal and module/theme source code. Drupal
-   * uses the built-in text for English by default, but if configured to allow
-   * translation/customization of English, we need to differentiate between the
-   * built-in language and the English translation.
+   * @param array $options
+   *   The properties used to construct the language.
    */
-  const LANGCODE_SYSTEM = 'system';
+  public function __construct(array $options = array()) {
+    // Set all the provided properties for the language.
+    foreach ($options as $name => $value) {
+      $this->{$name} = $value;
+    }
+    // If some options were not set, set sane defaults of a predefined language.
+    if (!isset($options['name']) || !isset($options['direction'])) {
+      $predefined = LanguageManager::getStandardLanguageList();
+      if (isset($predefined[$this->id])) {
+        if (!isset($options['name'])) {
+          $this->name = $predefined[$this->id][0];
+        }
+        if (!isset($options['direction']) && isset($predefined[$this->id][2])) {
+          $this->direction = $predefined[$this->id][2];
+        }
+      }
+    }
+  }
 
   /**
-   * The language code used when no language is explicitly assigned (yet).
-   *
-   * Should be used when language information is not available or cannot be
-   * determined. This special language code is useful when we know the data
-   * might have linguistic information, but we don't know the language.
-   *
-   * See http://www.w3.org/International/questions/qa-no-language#undetermined.
+   * {@inheritdoc}
    */
-  const LANGCODE_NOT_SPECIFIED = 'und';
+  public function getName() {
+    return $this->name;
+  }
 
   /**
-   * The language code used when the marked object has no linguistic content.
-   *
-   * Should be used when we explicitly know that the data referred has no
-   * linguistic content.
-   *
-   * See http://www.w3.org/International/questions/qa-no-language#nonlinguistic.
+   * {@inheritdoc}
    */
-  const LANGCODE_NOT_APPLICABLE = 'zxx';
+  public function setName($name) {
+    $this->name = $name;
 
-  /**
-   * Language code referring to the default language of data, e.g. of an entity.
-   *
-   * See the BCP 47 syntax for defining private language tags:
-   * http://www.rfc-editor.org/rfc/bcp/bcp47.txt
-   */
-  const LANGCODE_DEFAULT = 'x-default';
+    return $this;
+  }
 
   /**
-   * The language state when referring to configurable languages.
+   * {@inheritdoc}
    */
-  const STATE_CONFIGURABLE = 1;
+  public function getId() {
+    return $this->id;
+  }
 
   /**
-   * The language state when referring to locked languages.
+   * {@inheritdoc}
    */
-  const STATE_LOCKED = 2;
+  public function setId($id) {
+    $this->id = $id;
+
+    return $this;
+  }
 
   /**
-   * The language state used when referring to all languages.
+   * {@inheritdoc}
    */
-  const STATE_ALL = 3;
+  public function getDirection() {
+    return $this->direction;
+  }
 
   /**
-   * The language state used when referring to the site's default language.
+   * {@inheritdoc}
    */
-  const STATE_SITE_DEFAULT = 4;
+  public function setDirection($direction) {
+    $this->direction = $direction;
+
+    return $this;
+  }
 
   /**
-   * The type of language used to define the content language.
+   * {@inheritdoc}
    */
-  const TYPE_CONTENT = 'language_content';
+  public function getWeight() {
+    return $this->weight;
+  }
 
   /**
-   * The type of language used to select the user interface.
+   * {@inheritdoc}
    */
-  const TYPE_INTERFACE = 'language_interface';
+  public function setWeight($weight) {
+    $this->weight = $weight;
+
+    return $this;
+  }
 
   /**
-   * The type of language used for URLs.
+   * {@inheritdoc}
    */
-  const TYPE_URL = 'language_url';
+  public function isDefault() {
+    return $this->default;
+  }
 
   /**
-   * Language written left to right. Possible value of $language->direction.
+   * {@inheritdoc}
    */
-  const DIRECTION_LTR = 0;
+  public function setDefault($default) {
+    $this->default = $default;
+
+    return $this;
+  }
 
   /**
-   * Language written right to left. Possible value of $language->direction.
+   * {@inheritdoc}
    */
-  const DIRECTION_RTL = 1;
+  public function getNegotiationMethodId() {
+    return $this->method_id;
+  }
 
   /**
-   * Language constructor builds the default language object.
-   *
-   * @param array $options
-   *   The properties used to construct the language.
+   * {@inheritdoc}
    */
-  public function __construct(array $options = array()) {
-    // Set all the provided properties for the language.
-    foreach ($options as $name => $value) {
-      $this->{$name} = $value;
-    }
-    // If some options were not set, set sane defaults of a predefined language.
-    if (!isset($options['name']) || !isset($options['direction'])) {
-      $predefined = LanguageManager::getStandardLanguageList();
-      if (isset($predefined[$this->id])) {
-        if (!isset($options['name'])) {
-          $this->name = $predefined[$this->id][0];
-        }
-        if (!isset($options['direction']) && isset($predefined[$this->id][2])) {
-          $this->direction = $predefined[$this->id][2];
-        }
-      }
-    }
+  public function setNegotiationMethodId($method_id) {
+    $this->method_id = $method_id;
+
+    return $this;
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Language/LanguageInterface.php b/core/lib/Drupal/Core/Language/LanguageInterface.php
new file mode 100644
index 0000000..e718749
--- /dev/null
+++ b/core/lib/Drupal/Core/Language/LanguageInterface.php
@@ -0,0 +1,211 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Language\LanguageInterface.
+ */
+
+namespace Drupal\Core\Language;
+
+/**
+ * Defines a language.
+ */
+interface LanguageInterface {
+
+  /**
+   * Special system language code (only applicable to UI language).
+   *
+   * Refers to the language used in Drupal and module/theme source code. Drupal
+   * uses the built-in text for English by default, but if configured to allow
+   * translation/customization of English, we need to differentiate between the
+   * built-in language and the English translation.
+   */
+  const LANGCODE_SYSTEM = 'system';
+
+  /**
+   * The language code used when no language is explicitly assigned (yet).
+   *
+   * Should be used when language information is not available or cannot be
+   * determined. This special language code is useful when we know the data
+   * might have linguistic information, but we don't know the language.
+   *
+   * See http://www.w3.org/International/questions/qa-no-language#undetermined.
+   */
+  const LANGCODE_NOT_SPECIFIED = 'und';
+
+  /**
+   * The language code used when the marked object has no linguistic content.
+   *
+   * Should be used when we explicitly know that the data referred has no
+   * linguistic content.
+   *
+   * See http://www.w3.org/International/questions/qa-no-language#nonlinguistic.
+   */
+  const LANGCODE_NOT_APPLICABLE = 'zxx';
+
+  /**
+   * Language code referring to the default language of data, e.g. of an entity.
+   *
+   * See the BCP 47 syntax for defining private language tags:
+   * http://www.rfc-editor.org/rfc/bcp/bcp47.txt
+   */
+  const LANGCODE_DEFAULT = 'x-default';
+
+  /**
+   * The language state when referring to configurable languages.
+   */
+  const STATE_CONFIGURABLE = 1;
+
+  /**
+   * The language state when referring to locked languages.
+   */
+  const STATE_LOCKED = 2;
+
+  /**
+   * The language state used when referring to all languages.
+   */
+  const STATE_ALL = 3;
+
+  /**
+   * The language state used when referring to the site's default language.
+   */
+  const STATE_SITE_DEFAULT = 4;
+
+  /**
+   * The type of language used to define the content language.
+   */
+  const TYPE_CONTENT = 'language_content';
+
+  /**
+   * The type of language used to select the user interface.
+   */
+  const TYPE_INTERFACE = 'language_interface';
+
+  /**
+   * The type of language used for URLs.
+   */
+  const TYPE_URL = 'language_url';
+
+  /**
+   * Language written left to right. Possible value of $language->direction.
+   */
+  const DIRECTION_LTR = 0;
+
+  /**
+   * Language written right to left. Possible value of $language->direction.
+   */
+  const DIRECTION_RTL = 1;
+
+  /**
+   * Gets the name of the language.
+   *
+   * @return string
+   *   The human-readable English name of the language.
+   */
+  public function getName();
+
+  /**
+   * Sets the name of the language.
+   *
+   * @param string $name
+   *   The human-readable English name of the language.
+   *
+   * @return $this
+   */
+  public function setName($name);
+
+  /**
+   * Gets the ID (language code).
+   *
+   * @return string
+   *   The language code.
+   */
+  public function getId();
+
+  /**
+   * Sets the ID (language code).
+   *
+   * @param string $id
+   *   The language code.
+   *
+   * @return $this
+   */
+  public function setId($id);
+
+  /**
+   * Gets the text direction (left-to-right or right-to-left).
+   *
+   * @return int
+   *   Either self::DIRECTION_LTR or self::DIRECTION_RTL.
+   */
+  public function getDirection();
+
+  /**
+   * Sets the direction of the language.
+   *
+   * @param int $direction
+   *   Either self::DIRECTION_LTR or self::DIRECTION_RTL.
+   *
+   * @return $this
+   */
+  public function setDirection($direction);
+
+  /**
+   * Gets the weight of the language.
+   *
+   * @return int
+   *   The weight, used to order languages with larger positive weights sinking
+   *   items toward the bottom of lists.
+   */
+  public function getWeight();
+
+  /**
+   * Sets the weight of the language.
+   *
+   * @param int $weight
+   *   The weight, used to order languages with larger positive weights sinking
+   *   items toward the bottom of lists.
+   *
+   * @return $this
+   */
+  public function setWeight($weight);
+
+  /**
+   * Returns whether this language is the default language.
+   *
+   * @return bool
+   *   Whether the language is the default language.
+   */
+  public function isDefault();
+
+  /**
+   * Sets whether this language is the default language.
+   *
+   * @param bool $default
+   *   TRUE if it is the default language.
+   *
+   * @return $this
+   */
+  public function setDefault($default);
+
+  /**
+   * Gets the language negotiation method ID for this language.
+   *
+   * @return string
+   *   The method ID, for example
+   *   \Drupal\language\LanguageNegotiatorInterface::METHOD_ID.
+   */
+  public function getNegotiationMethodId();
+
+  /**
+   * Sets the language negotiation method ID for this language.
+   *
+   * @param string $method_id
+   *   The method ID, for example
+   *   \Drupal\language\LanguageNegotiatorInterface::METHOD_ID.
+   *
+   * @return $this
+   */
+  public function setNegotiationMethodId($method_id);
+
+}
diff --git a/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php b/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php
new file mode 100644
index 0000000..466ad87
--- /dev/null
+++ b/core/tests/Drupal/Tests/Core/Language/LanguageUnitTest.php
@@ -0,0 +1,107 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Tests\Core\Language\LanguageUnitTest.
+ */
+
+namespace Drupal\Tests\Core\Language;
+
+use Drupal\Core\Language\Language;
+use Drupal\Core\Language\LanguageInterface;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests \Drupal\Core\Language\Language.
+ *
+ * @group Drupal
+ * @group Language
+ */
+class LanguageUnitTest extends UnitTestCase {
+
+  /**
+   * The language under test.
+   *
+   * @var \Drupal\Core\Language\Language
+   */
+  protected $language;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getInfo() {
+    return array(
+      'description' => '',
+      'name' => '\Drupal\Core\Language\Language unit test',
+      'group' => 'System',
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    $this->language = new Language();
+  }
+
+  /**
+   * Tests name getter and setter methods.
+   *
+   * @covers \Drupal\Core\Language\Language::getName()
+   * @covers \Drupal\Core\Language\Language::setName()
+   */
+  public function testGetName() {
+    $name = $this->randomName();
+    $this->assertSame(spl_object_hash($this->language), spl_object_hash($this->language->setName($name)));
+    $this->assertSame($name, $this->language->getName());
+  }
+
+  /**
+   * Tests langcode ID getter and setter methods.
+   *
+   * @covers \Drupal\Core\Language\Language::getId()
+   * @covers \Drupal\Core\Language\Language::setId()
+   */
+  public function testGetLangcode() {
+    $language_code = $this->randomName(2);
+    $this->assertSame(spl_object_hash($this->language), spl_object_hash($this->language->setId($language_code)));
+    $this->assertSame($language_code, $this->language->getId());
+  }
+
+  /**
+   * Tests direction getter and setter methods.
+   *
+   * @covers \Drupal\Core\Language\Language::getDirection()
+   * @covers \Drupal\Core\Language\Language::setDirection()
+   */
+  public function testGetDirection() {
+    $direction = LanguageInterface::DIRECTION_RTL;
+    $this->assertSame(spl_object_hash($this->language), spl_object_hash($this->language->setDirection($direction)));
+    $this->assertSame($direction, $this->language->getDirection());
+  }
+
+  /**
+   * Tests isDefault() and default setter.
+   *
+   * @covers \Drupal\Core\Language\Language::isDefault()
+   * @covers \Drupal\Core\Language\Language::setDefault()
+   */
+  public function testIsDefault() {
+    $default = TRUE;
+    $this->assertSame(spl_object_hash($this->language), spl_object_hash($this->language->setDefault($default)));
+    $this->assertSame($default, $this->language->isDefault());
+  }
+
+  /**
+   * Tests negotiationMethodId getter and setter methods.
+   *
+   * @covers \Drupal\Core\Language\Language::getNegotiationMethodId()
+   * @covers \Drupal\Core\Language\Language::setNegotiationMethodId()
+   */
+  public function testGetNegotiationMethodId() {
+    $method_id = $this->randomName();
+    $this->assertSame(spl_object_hash($this->language), spl_object_hash($this->language->setNegotiationMethodId($method_id)));
+    $this->assertSame($method_id, $this->language->getNegotiationMethodId());
+  }
+
+}
