Multi-language url rewriting using Prettyfaces - jsf

I built my site to be Multi-language. I want the language code to be embedded in the address of page according to the locale. I have the following:
http://localhost:8080/Wirote/index
I want to have it as the following:
http://localhost:8080/Wirote/de/index --- display German content
http://localhost:8080/Wirote/en/index --- display English content
http://localhost:8080/Wirote/ar/index --- display Arabic content
To achieve this I followed the step in :
multi-language url rewiting. Is it possible?
pretty-config.xml
<url-mapping id="base">
<pattern value="/#{localeManger.language}"/>
</url-mapping>
<url-mapping id="index" parentId="base">
<pattern value="/index"/>
<view-id value="/index.xhtml"/>
</url-mapping>
faces-config.xml
<application>
<locale-config>
<default-locale>de</default-locale>
<supported-locale>en</supported-locale>
<supported-locale>ar</supported-locale>
</locale-config>
<resource-bundle>
<base-name>I18n.lang</base-name>
<var>sprache</var>
</resource-bundle>
</application>
LocaleManger.java
#ManagedBean(name = "localeManger")
#SessionScoped
public class LocaleManger implements Serializable{
private Locale locale;
private static final long serialVersionUID = 2756934361134603857L;
#PostConstruct
public void init() {
FacesContext.getCurrentInstance().getApplication().getDefaultLocale();
}
public Locale getLocale() {
return locale;
}
public String getLanguage() {
return locale.getLanguage();
}
public void setLanguage(String language) {
locale = new Locale(language);
FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
}}
Now when I run the project, I got only:
http://localhost:8080/Wirote/index
also the page is stuck, so I can't navigate to another using links in the index.xtml
alternative I add the following to the index.xhtml:
<f:metadata>
<f:viewParam name="locale" value="#{localeManger.language}"/>
</f:metadata>
pretty-config.xml
<url-mapping id="index">
<pattern value="/#{locale}/index"/>
<view-id value="/index.xhtml"/>
</url-mapping>
Now when I run the project, I get the following:
http://localhost:8080/Wirote/de/index
But when I try to change the language, by clicking on English or Arabic language switcher, it doesn't work correctly, the content of the page change, but the address page is not. But if I change it manually to
http://localhost:8080/Wirote/en/index or
http://localhost:8080/Wirote/ar/index
it display the correct content in Arabic and English, but I need the address to be changed automatically not manually.
How can I get the correct address related to current locale?

I'm not sure if this helps you, since you're attempting to do this using PrettyFaces, but Rewrite (the library PrettyFaces is based on) has a dedicated feature for internationalizing URLs:
https://github.com/ocpsoft/rewrite/blob/master/documentation/src/main/asciidoc/configuration/i18n.asciidoc
This might help you and if you are using PrettyFaces based on Rewrite, then you already have access to this feature.

Related

How to override a Language.properties from a theme?

I added new configuration settings to my Liferay theme inside the file liferay-look-and-feel.xml
<setting configurable="true" key="show-navigation" type="checkbox" value="true" />
In the control panel I can see the setting with show-navigation label.
I want to translate it to Show the Main Navigation using Language.properties inside the theme.
Then to accomplish this in my theme I added this files (theme\docroot\WEB-INF\src\content):
Language.properties
Language_en.properties
Language_fr.properties
Which each file contains the translation as so:
show-navigation=Show the Main Navigation
then in theme\docroot\WEB-INF\ I added liferay-hook.xml
<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
<language-properties>content/Language*.properties</language-properties>
</hook>
But it doesn't work. If I perform the same procedure for a portlet it works.
Why?
It's the name: You don't use content/Language*.properties, but just content/Language.properties. Otherwise I believe you're on the correct way to solve the problem, it's just this little detail

pretty faces does not work

I tried pretty faces with my jsf app.URL has not changed.I followed the steps mentioned on the site.
pom.xml
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-servlet</artifactId>
<version>2.0.12.Final</version>
</dependency>
<dependency>
<groupId>org.ocpsoft.rewrite</groupId>
<artifactId>rewrite-config-prettyfaces</artifactId>
<version>2.0.12.Final</version>
</dependency>
I added pretty-config.xml in WEB-INF/
pretty-config.xml
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="login">
<pattern value="/login" />
<view-id value="/pages/unsecure/login.jsf" />
</url-mapping>
</pretty-config>
my local project url(full url)
http://localhost:9080/projectName/pages/unsecure/login.jsf
I use myfaces2.2.7,spring/security,hibernate,tomcat7
Is there another setting I need to do?What I'm missing.I dont understand.
What exactly should I do?Thanks in advance..
UPDATE:
I don't get any error.just does not work. URL does not change..
The URL in the browser isn't going to change automatically. PrettyFaces maps pretty URLs to internal URLs. So if you request:
http://localhost:9080/projectName/login
You would actually see the /pages/unsecure/login.jsf page as specified in the configuration. Navigation using JSF navigation or internal redirects to this page will automatically use the pretty URL.
If you want to automatically redirect from the internal URL to the pretty URL from external Requests (like in your example,) then you need to add a rewrite condition to do that:
<pretty-config xmlns="http://ocpsoft.org/schema/rewrite-config-prettyfaces"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ocpsoft.org/schema/rewrite-config-prettyfaces
http://ocpsoft.org/xml/ns/prettyfaces/rewrite-config-prettyfaces.xsd">
<url-mapping id="login">
<pattern value="/login" />
<view-id value="/pages/unsecure/login.jsf" />
</url-mapping>
<rewrite match="/pages/unsecure/login.jsf" substitute="/login" redirect="301"/>
</pretty-config>
Alternatively, you can use Rewrite directly for both of these rules (since you are already using Rewrite with the PrettyFaces extension), using the Join rule:
#RewriteConfiguration
public class ExampleConfigurationProvider extends HttpConfigurationProvider
{
#Override
public int priority()
{
return 10;
}
#Override
public Configuration getConfiguration(final ServletContext context)
{
return ConfigurationBuilder.begin()
.addRule(Join.path("/login").to("/pages/unsecure/login.jsf").withInboundCorrection());
}
}
Note the .withInboundCorrection() method call. This sets up the inbound redirect from the OLD url to the NEW url automatically.
I hope this helps. Cheers!

How to place a JSF flow in a subfolder?

I'm introducing a JSF Faces flow into my application. This works, following the oracle documentation. But, only in the root folder.
Is it possible to place the JSF flow folder in a sub folder, else that root?
I can't get this working. That's all folks!
I solved this one myself.
A JSF flow definition can be done in 2 ways:
with configuration file: flowname-flow.xml
with configuration class: flowname.java
The first one can only define a flow-name, with the location defaulting to the root folder.
The second can define a location deeper in your folder structure.
Configuration file example: testflow.flow.xml
Only the id="testFlow" can be added to the definition, and not the path. This defaults to testFlow/testFlow.xhtml for the first page.
<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
<flow-definition id="testFlow">
<flow-return id="returnFromTestFlow">
<from-outcome>#{testFlow.returnValue}</from-outcome>
</flow-return>
</flow-definition>
</faces-config>
Configuration class example: TestFlow.java
Add the fully qualified path to the view node within this flow.
public class TestFlow implements Serializable {
private static final long serialVersionUID = 1L;
#Produces
#FlowDefinition
public Flow defineFlow(#FlowBuilderParameter FlowBuilder flowBuilder) {
String flowId = "testFlow";
flowBuilder.id("", flowId);
flowBuilder.viewNode(flowId,
"/other/location/flow/" + flowId + ".xhtml").
markAsStartNode();
flowBuilder.viewNode("testFlow2", "/other/location/flow/testFlow2.xhtml");
flowBuilder.viewNode("testFlow3", "/other/location/flow/testFlow3.xhtml");
...
That's all folks!

PrettyFaces using mapped urls and actions, i lose all my stylings

I have been using pretty faces for urls without issue until i started using mapped URLs feature (Section 3.6). http://ocpsoft.org/docs/prettyfaces/3.3.3/en-US/html/Configuration.html#config.actions
I'm getting the output and the actions i want to happen working fine. The problem though is i can't get to to any of my assets under assets folder. i'm getting a 404. The weird thing is that for every other config there hasn't been a problem. And isn't a problem when I run them together. The app is using a template so the links to css's, js's, etc.. are exactly the same. When I go to a plain ol' (e.g. /home) mapping they work fine, go to the other page with the action, they don't work. The template rendering does though. In fact the parameter injection and the action work as well.
PRETTY CONFIG:
<url-mapping id="home"> <!-- assets work -->
<pattern value="/home" />
<view-id value="/home.jsf" />
</url-mapping>
<url-mapping id="validate-token"> <!-- assets don't work -->
<pattern value="/validate-token/type/#{id:validateByTokenController.tokenType}/token/#{validateByTokenController.token}" />
<view-id value="/validate-token.jsf" />
<action>#{validateByTokenController.init}</action>
</url-mapping>
BEAN:
#RequestScoped
#Named
public class ValidateByTokenController {
private String tokenType;
private String token;
public void init() {
token = "J" + token;
tokenType = "J" + tokenType;
}
XHTML SAMPLE CSS LINKS: (same links for "home" config, but not for "validate-token")
<link rel="stylesheet"
href="assets/plugins/bootstrap/css/bootstrap.min.css" />
<link rel="stylesheet" href="assets/css/style.css" />
Thanks in advance.
The problem is that you are using relative URLs for your CSS files.
With an URL like /validate-token/type/foo/token/bar the browser thinks that /validate-token/type/foo/token/ is the current directory. So he tries to load the CSS file from /validate-token/type/foo/token/assets/css/style.css.
Try using absolute URLs for your CSS instead:
<link rel="stylesheet" href="#{request.contextPath}/assets/css/style.css" />

using pretty faces with web filters

Using Tomcat 7 --- Primefaces 3.4.1 --- javax faces 2.1.17 --- prettyfaces-jsf2 3.3.3
I configured pretty faces on my project correctly but my web filters are not working with new urls which are written by pretty faces.
Here is an example pretty-config.xml
<url-mapping id="home">
<pattern value="/home"/>
<view-id value="/secure/homepage.xhtml"/>
</url-mapping>
<url-mapping id="register">
<pattern value="/register"/>
<view-id value="/public/register.xhtml"/>
</url-mapping>
<url-mapping id="welcome">
<pattern value="/"/>
<view-id value="/public/welcome.xhtml"/>
</url-mapping>
<url-mapping id="profile">
<pattern value="/profile/#{userId}"/>
<view-id value="/profile.xhtml"/>
</url-mapping>
login(welcome) and register pages are in "public" folder, and their web filter is defined with annotation : #WebFilter("/public/*")
for my home page in "secure" folder (exactly there will be more pages in the folder), i defined a web filter also and its annotation : #WebFilter("/secure/*)
pretty urls are working fine, but these filters are only working when i write the original urls.
1) How can i repair my webfilters ?
2) I also want to block user for entering original url. I know that pretty faces is hiding original urls fully but is there a way to do it ?
-- SOLVED -- thanks for BalusC
if you defined your filters with annotations, you can configure dispatcher settings like
#WebFilter(urlPatterns = "/public/*", dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD})
PrettyFaces uses like many URL-rewriting solutions RequestDispatcher#forward() to forward the request to the desired target resource.
Servlet filters, when mapped without any <dispatcher>, listens by default on "initial" requests only, not on forwarded, included, nor error'ed requests.
So, when you map another servlet filter in web.xml after the PrettyFaces one, then it would by default not be triggered, unless you explicitly set a <dispatcher> on FORWARD next to the default of REQUEST (you should keep this one for the case PrettyFaces actually doesn't need to perform a forward).
<filter-mapping>
...
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
Or, for the case you're using #WebFilter on your filters, use the dispatcherTypes attribute:
#WebFilter(..., dispatcherTypes = { REQUEST, FORWARD })
Alternatively, if the filter in question doesn't change the request/response target in any way, e.g. setting the charset, compressing using Gzip, listening on exceptions, etc, then you can also just put it before the PrettyFaces one.

Resources