ISIS-903: adding PoReader impl along with new XxxTranslated facets

Also implementations of LocaleProvider and new UrlResolver service from Wicket.

However, not there yet; the .po file read/write needs to handle plural form, 
and the interface for TranslationService needs to be extended similarly


Project: http://git-wip-us.apache.org/repos/asf/isis/repo
Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/b0470ba5
Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/b0470ba5
Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/b0470ba5

Branch: refs/heads/master
Commit: b0470ba5632c9b0800e7e011be114295b07a1348
Parents: 1ee748e
Author: Dan Haywood <[email protected]>
Authored: Tue Feb 17 11:11:29 2015 +0000
Committer: Dan Haywood <[email protected]>
Committed: Wed Feb 18 14:07:38 2015 +0000

----------------------------------------------------------------------
 .../viewer/services/LocaleProviderWicket.java   | 47 +++++++++++++
 .../viewer/services/UrlResolverWicket.java      | 65 ++++++++++++++++++
 .../applib/services/i18n/LocaleProvider.java    | 29 ++++++++
 .../isis/applib/services/i18n/UrlResolver.java  | 29 ++++++++
 .../applib/services/locale/LocaleProvider.java  | 29 --------
 .../facets/SingleStringValueFacetAbstract.java  |  6 +-
 .../all/i18n/DescribedAsFacetTranslated.java    | 52 ++++++++++++++
 .../facets/all/i18n/I18nFacetFactory.java       | 19 ++----
 .../facets/all/i18n/NamedFacetTranslated.java   | 56 +++++++++++++++
 .../facets/all/i18n/PluralFacetTranslated.java  | 50 ++++++++++++++
 .../object/plural/PluralFacetAbstract.java      |  7 +-
 .../plural/inferred/PluralFacetInferred.java    |  2 +-
 .../services/i18n/LocaleProviderDefault.java    |  2 +-
 .../core/metamodel/services/i18n/po/Block.java  | 65 ++++++++++++++++++
 .../metamodel/services/i18n/po/PoReader.java    | 72 ++++++++++++++------
 .../services/i18n/po/TranslationServicePo.java  | 17 ++++-
 .../dflt/ObjectSpecificationDefault.java        | 29 ++++++--
 .../services/i18n/po/PoReaderTest.java          | 68 ++++++++++++++----
 18 files changed, 559 insertions(+), 85 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/LocaleProviderWicket.java
----------------------------------------------------------------------
diff --git 
a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/LocaleProviderWicket.java
 
b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/LocaleProviderWicket.java
new file mode 100644
index 0000000..966f8fb
--- /dev/null
+++ 
b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/LocaleProviderWicket.java
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.wicket.viewer.services;
+
+import java.util.Locale;
+import org.apache.wicket.Session;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.i18n.LocaleProvider;
+
+
+/**
+ * An implementation that provides the locale of the current session.
+ */
+@DomainService
+public class LocaleProviderWicket implements LocaleProvider {
+
+    public static Logger LOG = 
LoggerFactory.getLogger(LocaleProviderWicket.class);
+
+    @Programmatic
+    @Override
+    public Locale getLocale() {
+        return getSession().getLocale();
+    }
+
+    protected Session getSession() {
+        return Session.get();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/UrlResolverWicket.java
----------------------------------------------------------------------
diff --git 
a/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/UrlResolverWicket.java
 
b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/UrlResolverWicket.java
new file mode 100644
index 0000000..d98093f
--- /dev/null
+++ 
b/component/viewer/wicket/impl/src/main/java/org/apache/isis/viewer/wicket/viewer/services/UrlResolverWicket.java
@@ -0,0 +1,65 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.viewer.wicket.viewer.services;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+import javax.servlet.ServletContext;
+import com.google.common.base.Charsets;
+import com.google.common.io.CharSource;
+import com.google.common.io.Resources;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.isis.applib.annotation.DomainService;
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.services.i18n.UrlResolver;
+import org.apache.isis.viewer.wicket.viewer.IsisWicketApplication;
+
+
+/**
+ * An implementation that reads from /WEB-INF/...
+ */
+@DomainService
+public class UrlResolverWicket implements UrlResolver {
+
+    public static Logger LOG = 
LoggerFactory.getLogger(UrlResolverWicket.class);
+
+    @Override
+    @Programmatic
+    public List<String> readLines(final String file) {
+        try {
+            final ServletContext servletContext = 
getIsisWicketApplication().getServletContext();
+            final URL url = servletContext.getResource("/WEB-INF/" + file);
+            return readLines(url);
+        } catch (final IOException ignored) {
+            return null;
+        }
+    }
+
+    private static List<String> readLines(final URL url) throws IOException {
+        final CharSource charSource = Resources.asCharSource(url, 
Charsets.UTF_8);
+        return charSource.readLines();
+    }
+
+    protected IsisWicketApplication getIsisWicketApplication() {
+        return IsisWicketApplication.get();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/applib/src/main/java/org/apache/isis/applib/services/i18n/LocaleProvider.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/LocaleProvider.java
 
b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/LocaleProvider.java
new file mode 100644
index 0000000..9fe73d3
--- /dev/null
+++ 
b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/LocaleProvider.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.i18n;
+
+import java.util.Locale;
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface LocaleProvider {
+
+    @Programmatic
+    Locale getLocale();
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/applib/src/main/java/org/apache/isis/applib/services/i18n/UrlResolver.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/services/i18n/UrlResolver.java
 
b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/UrlResolver.java
new file mode 100644
index 0000000..5dcb614
--- /dev/null
+++ 
b/core/applib/src/main/java/org/apache/isis/applib/services/i18n/UrlResolver.java
@@ -0,0 +1,29 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib.services.i18n;
+
+import java.util.List;
+import org.apache.isis.applib.annotation.Programmatic;
+
+public interface UrlResolver {
+
+    @Programmatic
+    public List<String> readLines(final String file);
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java
----------------------------------------------------------------------
diff --git 
a/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java
 
b/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java
deleted file mode 100644
index 5a34285..0000000
--- 
a/core/applib/src/main/java/org/apache/isis/applib/services/locale/LocaleProvider.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.services.locale;
-
-import java.util.Locale;
-import org.apache.isis.applib.annotation.Programmatic;
-
-public interface LocaleProvider {
-
-    @Programmatic
-    Locale getLocale();
-
-}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/SingleStringValueFacetAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/SingleStringValueFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/SingleStringValueFacetAbstract.java
index 1fed8c9..ad86d5f 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/SingleStringValueFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/SingleStringValueFacetAbstract.java
@@ -27,7 +27,11 @@ public abstract class SingleStringValueFacetAbstract extends 
FacetAbstract imple
     private final String value;
 
     public SingleStringValueFacetAbstract(final Class<? extends Facet> 
facetType, final FacetHolder holder, final String value) {
-        super(facetType, holder, Derivation.NOT_DERIVED);
+        this(facetType, holder, value, Derivation.NOT_DERIVED);
+    }
+
+    public SingleStringValueFacetAbstract(final Class<? extends Facet> type, 
final FacetHolder holder, final String value, final Derivation derivation) {
+        super(type, holder, derivation);
         this.value = value;
     }
 

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/DescribedAsFacetTranslated.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/DescribedAsFacetTranslated.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/DescribedAsFacetTranslated.java
new file mode 100644
index 0000000..4e67f26
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/DescribedAsFacetTranslated.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.all.i18n;
+
+import java.util.Locale;
+import org.apache.isis.applib.services.i18n.LocaleProvider;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
+
+public class DescribedAsFacetTranslated extends FacetAbstract implements 
DescribedAsFacet{
+
+    private final String context;
+    private final String originalText;
+    private final TranslationService translationService;
+    private final LocaleProvider localeProvider;
+
+    public DescribedAsFacetTranslated(
+            final String context, final String originalText,
+            final TranslationService translationService, final LocaleProvider 
localeProvider,
+            final IdentifiedHolder holder) {
+        super(DescribedAsFacet.class, holder, Derivation.NOT_DERIVED);
+        this.context = context;
+        this.originalText = originalText;
+        this.translationService = translationService;
+        this.localeProvider = localeProvider;
+    }
+
+    @Override
+    public String value() {
+        final Locale locale = localeProvider.getLocale();
+        return translationService.translate(context, originalText, locale);
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java
index f866f94..0b6e689 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/I18nFacetFactory.java
@@ -19,17 +19,13 @@
 package org.apache.isis.core.metamodel.facets.all.i18n;
 
 
-import java.util.Locale;
-import java.util.Objects;
 import com.google.common.base.Strings;
+import org.apache.isis.applib.services.i18n.LocaleProvider;
 import org.apache.isis.applib.services.i18n.TranslationService;
-import org.apache.isis.applib.services.locale.LocaleProvider;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
-import 
org.apache.isis.core.metamodel.facetdecorator.i18n.internal.DescribedAsFacetWrapI18n;
-import 
org.apache.isis.core.metamodel.facetdecorator.i18n.internal.NamedFacetWrapI18n;
 import org.apache.isis.core.metamodel.facets.ContributeeMemberFacetFactory;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
 import org.apache.isis.core.metamodel.facets.all.describedas.DescribedAsFacet;
@@ -103,10 +99,8 @@ public class I18nFacetFactory extends FacetFactoryAbstract 
implements Contribute
         final TranslationService translationService = 
lookupTranslationService();
         final LocaleProvider localeProvider = lookupLocaleProvider();
 
-        final Locale locale = localeProvider.getLocale();
-        final String translatedText = translationService.translate(context, 
originalText, locale);
-        if(!Objects.equals(originalText, translatedText)) {
-            FacetUtil.addFacet(new NamedFacetWrapI18n(translatedText, 
facetHolder));
+        if(translationService != null && localeProvider != null) {
+            FacetUtil.addFacet(new NamedFacetTranslated(context, originalText, 
translationService, localeProvider, facetHolder));
         }
     }
 
@@ -125,11 +119,10 @@ public class I18nFacetFactory extends 
FacetFactoryAbstract implements Contribute
         final TranslationService translationService = 
lookupTranslationService();
         final LocaleProvider localeProvider = lookupLocaleProvider();
 
-        final Locale locale = localeProvider.getLocale();
-        final String translatedText = translationService.translate(context, 
originalText, locale);
-        if(!Objects.equals(originalText, translatedText)) {
-            FacetUtil.addFacet(new DescribedAsFacetWrapI18n(translatedText, 
holder));
+        if(translationService != null && localeProvider != null) {
+            FacetUtil.addFacet(new DescribedAsFacetTranslated(context, 
originalText, translationService, localeProvider, holder));
         }
+
     }
 
     private boolean isNullOrEmptyWhenTrimmed(final String originalText) {

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/NamedFacetTranslated.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/NamedFacetTranslated.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/NamedFacetTranslated.java
new file mode 100644
index 0000000..6e7fb31
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/NamedFacetTranslated.java
@@ -0,0 +1,56 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.all.i18n;
+
+import org.apache.isis.applib.services.i18n.LocaleProvider;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
+import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
+
+public class NamedFacetTranslated extends FacetAbstract implements NamedFacet {
+
+    final TranslationService translationService;
+    final LocaleProvider localeProvider;
+    String context;
+    String originalText;
+
+    public NamedFacetTranslated(
+            final String context, final String originalText,
+            final TranslationService translationService, final LocaleProvider 
localeProvider,
+            final IdentifiedHolder facetHolder) {
+        super(NamedFacet.class, facetHolder, Derivation.NOT_DERIVED);
+        this.context = context;
+        this.originalText = originalText;
+        this.translationService = translationService;
+        this.localeProvider = localeProvider;
+    }
+
+    @Override
+    public String value() {
+        return translationService.translate(context, originalText, 
localeProvider.getLocale());
+    }
+
+    @Override
+    public boolean escaped() {
+        final NamedFacet underlyingFacet = (NamedFacet) getUnderlyingFacet();
+        return underlyingFacet != null && underlyingFacet.escaped();
+    }
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/PluralFacetTranslated.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/PluralFacetTranslated.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/PluralFacetTranslated.java
new file mode 100644
index 0000000..89ece86
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/all/i18n/PluralFacetTranslated.java
@@ -0,0 +1,50 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.isis.core.metamodel.facets.all.i18n;
+
+import org.apache.isis.applib.services.i18n.LocaleProvider;
+import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.core.commons.lang.StringExtensions;
+import org.apache.isis.core.metamodel.facetapi.FacetAbstract;
+import org.apache.isis.core.metamodel.facetapi.FacetHolder;
+import org.apache.isis.core.metamodel.facets.object.plural.PluralFacet;
+
+public class PluralFacetTranslated extends FacetAbstract implements 
PluralFacet {
+
+    private final TranslationService translationService;
+    private final LocaleProvider localeProvider;
+    private String context;
+    private String originalText;
+
+    public PluralFacetTranslated(final NamedFacetTranslated facet, final 
FacetHolder facetHolder) {
+        super(PluralFacet.class, facetHolder, Derivation.DERIVED);
+        this.translationService = facet.translationService;
+        this.localeProvider = facet.localeProvider;
+        this.context = facet.context;
+        this.originalText = facet.originalText;
+    }
+
+    @Override
+    public String value() {
+        final String singularName = translationService.translate(context, 
originalText, localeProvider.getLocale());
+        return StringExtensions.asPluralName(singularName);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/PluralFacetAbstract.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/PluralFacetAbstract.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/PluralFacetAbstract.java
index 24f4075..64c8fd0 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/PluralFacetAbstract.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/PluralFacetAbstract.java
@@ -30,7 +30,12 @@ public abstract class PluralFacetAbstract extends 
SingleStringValueFacetAbstract
     }
 
     public PluralFacetAbstract(final String value, final FacetHolder holder) {
-        super(type(), holder, value);
+        this(value, holder, Derivation.NOT_DERIVED);
     }
 
+    public PluralFacetAbstract(final String value, final FacetHolder holder, 
final Derivation derivation) {
+        super(type(), holder, value, derivation);
+    }
+
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/inferred/PluralFacetInferred.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/inferred/PluralFacetInferred.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/inferred/PluralFacetInferred.java
index 82baefb0..572c3d3 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/inferred/PluralFacetInferred.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/plural/inferred/PluralFacetInferred.java
@@ -25,7 +25,7 @@ import 
org.apache.isis.core.metamodel.facets.object.plural.PluralFacetAbstract;
 public class PluralFacetInferred extends PluralFacetAbstract {
 
     public PluralFacetInferred(final String value, final FacetHolder holder) {
-        super(value, holder);
+        super(value, holder, Derivation.DERIVED);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java
index 4b7ec49..6df4111 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/LocaleProviderDefault.java
@@ -21,7 +21,7 @@ package org.apache.isis.core.metamodel.services.i18n;
 
 import java.util.Locale;
 import org.apache.isis.applib.annotation.Programmatic;
-import org.apache.isis.applib.services.locale.LocaleProvider;
+import org.apache.isis.applib.services.i18n.LocaleProvider;
 
 /**
  * Not annotated with &#64;DomainService, but is registered as a fallback by 
<tt>ServicesInstallerFallback</tt>.

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/Block.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/Block.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/Block.java
new file mode 100644
index 0000000..d4543ad
--- /dev/null
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/Block.java
@@ -0,0 +1,65 @@
+package org.apache.isis.core.metamodel.services.i18n.po;
+
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import com.google.common.collect.Lists;
+
+class Block {
+
+    private enum State {
+        CONTEXT,
+        MSGID,
+        MSGSTR
+    }
+
+    private static final Pattern contextPattern = Pattern.compile("^#: 
(?<context>.+)$");
+    private static final Pattern msgidPattern = Pattern.compile("^msgid 
\"(?<msgid>.+)\"$");
+    private static final Pattern msgstrPattern = Pattern.compile("^msgstr 
\"(?<msgstr>.+)\"$");
+
+    State state = State.CONTEXT;
+
+    List<String> contextList = Lists.newArrayList();
+    String msgid = null;
+    String msgstr = null;
+
+    Block parseLine(final String line, final Map<MsgIdAndContext, String> 
translationsByKey) {
+        if (state == State.CONTEXT) {
+            final Matcher matcher = contextPattern.matcher(line);
+            if (matcher.matches()) {
+                final String context = matcher.group("context");
+                contextList.add(context);
+            } else {
+                state = State.MSGID;
+            }
+        }
+        if (state == State.MSGID) {
+            final Matcher matcher = msgidPattern.matcher(line);
+            if (matcher.matches()) {
+                msgid = matcher.group("msgid");
+            } else {
+                state = State.MSGSTR;
+            }
+        }
+        if (state == State.MSGSTR) {
+            final Matcher matcher = msgstrPattern.matcher(line);
+            if (matcher.matches()) {
+                msgstr = matcher.group("msgstr");
+            }
+            append(translationsByKey);
+            return new Block();
+        }
+        return this;
+    }
+
+    private void append(final Map<MsgIdAndContext, String> translationsByKey) {
+        if(msgid != null && msgstr != null) {
+            for (String context : contextList) {
+                final MsgIdAndContext mc = new MsgIdAndContext(msgid, context);
+                translationsByKey.put(mc, msgstr);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/PoReader.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/PoReader.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/PoReader.java
index 514c81c..83806e6 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/PoReader.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/PoReader.java
@@ -18,37 +18,53 @@
  */
 package org.apache.isis.core.metamodel.services.i18n.po;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import com.google.common.base.Charsets;
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.io.Files;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 class PoReader extends PoAbstract {
 
+    public static final String LOCATION_BASE_URL = 
"isis.services.translation.po.locationBaseUrl";
     public static Logger LOG = LoggerFactory.getLogger(PoReader.class);
 
     private final Map<Locale, Map<MsgIdAndContext, String>> 
translationByKeyByLocale = Maps.newHashMap();
 
+    /**
+     * The basename of the translations file, hard-coded to 
<tt>translations</tt>.
+     *
+     * <p>
+     *     This means that the reader will search for 
<tt>translations_en-US.po</tt>, <tt>translations_en.po</tt>,
+     *     <tt>translations.po</tt>, according to the location that the 
provided {@link org.apache.isis.applib.services.i18n.UrlResolver} searches.  
For example, if using the Wicket implementation, then will search for these 
files
+     *     under <tt>/WEB-INF</tt> directory.
+     * </p>
+     */
+    private final String basename = "translations";
+
+    private List<String> fallback;
+
     public PoReader(final TranslationServicePo translationServicePo) {
         super(translationServicePo);
     }
 
     //region > init, shutdown
     void init(final Map<String,String> config) {
+        fallback = readPoElseNull(Locale.ROOT);
+        if(fallback == null) {
+            LOG.warn("No fallback translations found");
+            fallback = Collections.emptyList();
+        }
     }
 
     void shutdown() {
     }
     //endregion
 
-
     public String translate(final String context, final String msgId, final 
Locale targetLocale) {
 
         final Map<MsgIdAndContext, String> translationsByKey = 
readAndCacheTranslationsIfRequired(targetLocale);
@@ -82,34 +98,52 @@ class PoReader extends PoAbstract {
         return translationsByKey;
     }
 
+
     /**
      * @param locale - the .po file to load
      * @param translationsByKey - the translations to be populated
      */
     private void read(final Locale locale, final Map<MsgIdAndContext, String> 
translationsByKey) {
-        final List<String> fileContents = readFile(locale);
+        final List<String> contents = readPo(locale);
 
-        // TODO: parse fileContents into translationsByKey
+        Block block = new Block();
+        for (final String line : contents) {
+            block = block.parseLine(line, translationsByKey);
+        }
     }
 
-    List<String> readFile(final Locale locale) {
-        final File file = locateFile(locale);
-        try {
-            return Files.readLines(file, Charsets.UTF_8);
-        } catch (final IOException ex) {
-            LOG.warn("Could not locate file for locale: " + locale, ex);
-            return Collections.emptyList();
+    protected List<String> readPo(final Locale locale) {
+        final List<String> lines = readPoElseNull(locale);
+        if(lines != null) {
+            return lines;
         }
+        LOG.warn("Could not locate translations for locale: " + locale + ", 
using fallback");
+        return fallback;
     }
 
-    File locateFile(final Locale locale) {
+    private List<String> readPoElseNull(final Locale locale) {
+        final String country = locale.getCountry().toUpperCase(Locale.ROOT);
+        final String language = locale.getLanguage().toLowerCase(Locale.ROOT);
+
+        final List<String> candidates = Lists.newArrayList();
+        if(!Strings.isNullOrEmpty(language)) {
+            if(!Strings.isNullOrEmpty(country)) {
+                candidates.add(basename + "_" + language + "-" + country+ 
".po");
+            }
+            candidates.add(basename + "_" + language + ".po");
+        }
+
+        for (final String candidate : candidates) {
+            final List<String> lines = readUrl(candidate);
+            if(lines != null) {
+                return lines;
+            }
+        }
         return null;
     }
 
-    private String translate(final Locale locale, final MsgIdAndContext key) {
-        // TODO
-        return key.getMsgId();
+    private List<String> readUrl(final String candidate) {
+        return translationServicePo.urlResolver.readLines(candidate);
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/TranslationServicePo.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/TranslationServicePo.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/TranslationServicePo.java
index a8cf426..5bebc99 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/TranslationServicePo.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/i18n/po/TranslationServicePo.java
@@ -22,10 +22,12 @@ import java.util.Locale;
 import java.util.Map;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
+import javax.inject.Inject;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.services.i18n.TranslationService;
+import org.apache.isis.applib.services.i18n.UrlResolver;
 
 /**
  * Not annotated with &#64;DomainService, but is registered as a fallback by 
<tt>ServicesInstallerFallback</tt>.
@@ -39,7 +41,7 @@ public class TranslationServicePo implements 
TranslationService {
     private PoAbstract po;
 
     public TranslationServicePo() {
-        po = new PoWriter(this);
+        po = new PoReader(this);
     }
 
     //region > init, shutdown
@@ -47,13 +49,19 @@ public class TranslationServicePo implements 
TranslationService {
     @Programmatic
     @PostConstruct
     public void init(final Map<String,String> config) {
+
         final String deploymentType = config.get("isis.deploymentType");
         prototype = deploymentType==null ||
                     deploymentType.toLowerCase().contains("prototype") ||
                     deploymentType.toLowerCase().contains("test") ;
 
-        if (!prototype) {
-            po = new PoReader(this);
+        String translationMode = 
config.get("isis.services.translation.po.mode");
+        final boolean forceRead =
+                "read".equalsIgnoreCase(translationMode) ||
+                "reader".equalsIgnoreCase(translationMode);
+
+        if (prototype && !forceRead) {
+            po = new PoWriter(this);
         }
         po.init(config);
     }
@@ -86,4 +94,7 @@ public class TranslationServicePo implements 
TranslationService {
         return  ((PoWriter)po).toPo();
     }
 
+    @Inject
+    UrlResolver urlResolver;
+
 }

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index 0a1c7c2..09355a0 100644
--- 
a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ 
b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -41,6 +41,8 @@ import org.apache.isis.core.metamodel.facetapi.Facet;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.FacetedMethod;
 import org.apache.isis.core.metamodel.facets.ImperativeFacet;
+import org.apache.isis.core.metamodel.facets.all.i18n.NamedFacetTranslated;
+import org.apache.isis.core.metamodel.facets.all.i18n.PluralFacetTranslated;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacet;
 import org.apache.isis.core.metamodel.facets.all.named.NamedFacetInferred;
 import org.apache.isis.core.metamodel.facets.object.callbacks.CallbackFacet;
@@ -53,10 +55,24 @@ import 
org.apache.isis.core.metamodel.facets.object.value.ValueFacet;
 import org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacet;
 import org.apache.isis.core.metamodel.facets.object.wizard.WizardFacet;
 import org.apache.isis.core.metamodel.runtimecontext.ServicesInjector;
-import org.apache.isis.core.metamodel.spec.*;
-import org.apache.isis.core.metamodel.spec.feature.*;
+import org.apache.isis.core.metamodel.spec.ActionType;
+import org.apache.isis.core.metamodel.spec.ObjectInstantiationException;
+import org.apache.isis.core.metamodel.spec.ObjectSpecification;
+import org.apache.isis.core.metamodel.spec.ObjectSpecificationException;
+import org.apache.isis.core.metamodel.spec.SpecificationContext;
+import org.apache.isis.core.metamodel.spec.feature.Contributed;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAction;
+import org.apache.isis.core.metamodel.spec.feature.ObjectAssociation;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMember;
+import org.apache.isis.core.metamodel.spec.feature.ObjectMemberContext;
 import 
org.apache.isis.core.metamodel.specloader.classsubstitutor.ClassSubstitutor;
-import org.apache.isis.core.metamodel.specloader.specimpl.*;
+import org.apache.isis.core.metamodel.specloader.specimpl.CreateObjectContext;
+import 
org.apache.isis.core.metamodel.specloader.specimpl.FacetedMethodsBuilder;
+import 
org.apache.isis.core.metamodel.specloader.specimpl.FacetedMethodsBuilderContext;
+import org.apache.isis.core.metamodel.specloader.specimpl.ObjectActionImpl;
+import 
org.apache.isis.core.metamodel.specloader.specimpl.ObjectSpecificationAbstract;
+import 
org.apache.isis.core.metamodel.specloader.specimpl.OneToManyAssociationImpl;
+import 
org.apache.isis.core.metamodel.specloader.specimpl.OneToOneAssociationImpl;
 
 public class ObjectSpecificationDefault extends ObjectSpecificationAbstract 
implements DebuggableWithTitle, FacetHolder {
 
@@ -186,7 +202,12 @@ public class ObjectSpecificationDefault extends 
ObjectSpecificationAbstract impl
 
         PluralFacet pluralFacet = getFacet(PluralFacet.class);
         if (pluralFacet == null) {
-            pluralFacet = new 
PluralFacetInferred(StringExtensions.asPluralName(namedFacet.value()), this);
+            if(namedFacet instanceof NamedFacetTranslated) {
+                final NamedFacetTranslated facet = (NamedFacetTranslated) 
namedFacet;
+                pluralFacet = new PluralFacetTranslated(facet, this);
+            } else {
+                pluralFacet = new 
PluralFacetInferred(StringExtensions.asPluralName(namedFacet.value()), this);
+            }
             addFacet(pluralFacet);
         }
     }

http://git-wip-us.apache.org/repos/asf/isis/blob/b0470ba5/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/i18n/po/PoReaderTest.java
----------------------------------------------------------------------
diff --git 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/i18n/po/PoReaderTest.java
 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/i18n/po/PoReaderTest.java
index bbab018..6b516f2 100644
--- 
a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/i18n/po/PoReaderTest.java
+++ 
b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/services/i18n/po/PoReaderTest.java
@@ -3,7 +3,6 @@ package org.apache.isis.core.metamodel.services.i18n.po;
 import java.util.List;
 import java.util.Locale;
 import com.google.common.collect.Lists;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import static org.hamcrest.CoreMatchers.equalTo;
@@ -14,9 +13,8 @@ public class PoReaderTest {
 
     PoReader poReader;
 
-    public static class ReadFile extends PoReaderTest {
+    public static class Translate extends PoReaderTest {
 
-        @Ignore // TODO
         @Test
         public void singleContext() throws Exception {
 
@@ -28,11 +26,11 @@ public class PoReaderTest {
 
             poReader = new PoReader(null) {
                 @Override
-                List<String> readFile(final Locale locale) {
+                protected List<String> readPo(final Locale locale) {
                     final List<String> lines = Lists.newArrayList();
                     lines.add(String.format("#: %s", context));
-                    lines.add(String.format("msgid: \"%s\"", msgId));
-                    lines.add(String.format("msgstr: \"%s\"", msgStr));
+                    lines.add(String.format("msgid \"%s\"", msgId));
+                    lines.add(String.format("msgstr \"%s\"", msgStr));
                     return lines;
                 }
             };
@@ -44,7 +42,6 @@ public class PoReaderTest {
             assertThat(translated, is(equalTo(msgStr)));
         }
 
-        @Ignore // TODO
         @Test
         public void multipleContext() throws Exception {
 
@@ -58,12 +55,12 @@ public class PoReaderTest {
 
             poReader = new PoReader(null) {
                 @Override
-                List<String> readFile(final Locale locale) {
+                protected List<String> readPo(final Locale locale) {
                     final List<String> lines = Lists.newArrayList();
                     lines.add(String.format("#: %s", context1));
                     lines.add(String.format("#: %s", context2));
-                    lines.add(String.format("msgid: \"%s\"", msgId));
-                    lines.add(String.format("msgstr: \"%s\"", msgStr));
+                    lines.add(String.format("msgid \"%s\"", msgId));
+                    lines.add(String.format("msgstr \"%s\"", msgStr));
                     return lines;
                 }
             };
@@ -80,7 +77,53 @@ public class PoReaderTest {
             assertThat(translated2, is(equalTo(msgStr)));
         }
 
-        @Ignore // TODO
+        @Test
+        public void multipleBlocks() throws Exception {
+
+            // given
+            final String context1 =
+                    
"org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#object()";
+            final String msgid1 = "Work of art";
+            final String msgstr1 = "Objet d'art";
+
+            final String context2 =
+                    
"org.apache.isis.applib.services.bookmark.BookmarkHolderAssociationContributions#lookup()";
+            final String msgid2 = "Lookup";
+            final String msgstr2 = "Look up";
+
+            poReader = new PoReader(null) {
+                @Override
+                protected List<String> readPo(final Locale locale) {
+                    final List<String> lines = Lists.newArrayList();
+                    lines.add(String.format("#: %s", context1));
+                    lines.add(String.format("msgid \"%s\"", msgid1));
+                    lines.add(String.format("msgstr \"%s\"", msgstr1));
+
+                    lines.add(String.format(""));
+                    lines.add(String.format("# "));
+
+                    lines.add(String.format("#: %s", context2));
+                    lines.add(String.format("msgid \"%s\"", msgid2));
+                    lines.add(String.format("msgstr \"%s\"", msgstr2));
+
+                    lines.add(String.format(""));
+                    return lines;
+                }
+            };
+
+            // when
+            final String translated1 = poReader.translate(context1, msgid1, 
Locale.FRENCH);
+
+            // then
+            assertThat(translated1, is(equalTo(msgstr1)));
+
+            // when
+            final String translated2 = poReader.translate(context2, msgid2, 
Locale.FRENCH);
+
+            // then
+            assertThat(translated2, is(equalTo(msgstr2)));
+        }
+
         @Test
         public void noTranslation() throws Exception {
 
@@ -88,7 +131,7 @@ public class PoReaderTest {
 
             poReader = new PoReader(null) {
                 @Override
-                List<String> readFile(final Locale locale) {
+                protected List<String> readPo(final Locale locale) {
                     return Lists.newArrayList();
                 }
             };
@@ -99,7 +142,6 @@ public class PoReaderTest {
             // then
             assertThat(translated, is(equalTo("Something to translate")));
        }
-
     }
 
 }
\ No newline at end of file

Reply via email to