Re: SEO URL supporting l10n/i18n with PrettyFaces

Splash Forums PrettyFaces Users SEO URL supporting l10n/i18n with PrettyFaces Re: SEO URL supporting l10n/i18n with PrettyFaces

#23451

The solution consists of three components.

A managed bean:

private UIViewRoot vr;
private ResourceBundle rb;
/**
* Constructs a BreadcrumbHandler object handling the breadcrumbs of view.
*/
public BreadcrumbHandler() {
this.vr = FacesContext.getCurrentInstance().getViewRoot();
this.rb = ResourceBundle.getBundle(VALUE_RB_VARNAME, this.vr.getLocale());
}

/**
* Providing the URI of the current view.
* @return String, representing the URI of the current view.
*/
private String getUri() {
String uri;
uri = this.vr.getViewId();
uri = uri.substring(0, uri.indexOf(EXT));
//return this.uri = uri;
return uri;
}

/**
* Providing an URI reduced by its highest element.
* @param uri String, representing the given URI.
* @return String, representing the given URI reduced by its highest element.
*/
private String getUriBefore(String uri) {
return uri.substring(0, uri.lastIndexOf("/"));
}

/**
* Providing the label key for an given URI.
* @param uri String, representing the URI, for what a label key should be provided.
* @return String, representing the label key for the given URI.
*/
private String getKey(String uri) {
String key = uri;
key = key.substring(key.indexOf(ROOT) + ROOT.length(), key.length());
key = key.replaceAll("/", ".");
key = KEY_LABEL_LINK_INTERNAL_PFX + key;
return key;
}

/**
* Providing the localized label for a given key.
* @param key String, representing the key, for what a label should be provided.
* @return String, representing the localized label for the given key.
*/
private String getLabel(String key) {
String label;
label = this.rb.getString(key);
if (null == label) {
label = "TBD";
}
//return this.label = label;
return label;
}

/**
* TODO has to become a listener for locale changes
* Assembling breadcrumbs
* @return List<String[]> containing all breadcrumbs. Each breadcrumb consists of an URI, a label and
* a CCS style class name.
*/
public List<String[]> getBreadcrumbs() {
List<String[]> breadcrumbs = new ArrayList<String[]>();
// Retrieving leaf data
String uri = this.getUri();
String key = this.getKey(uri);
String label = this.getLabel(key);
String style = STYLE_CLASS_LEAF;
// If we are not at home
if (!uri.endsWith(HOME)) {
Boolean notRoot = Boolean.TRUE;
while (notRoot) {
String[] bc = new String[3];
bc[0] = uri;
bc[1] = label;
bc[2] = style;
logger.info("BreadcrumbHandler() getBreadcrumbs [leafe] uri=" + uri + " key=" + key + " label=" + label);
breadcrumbs.add(bc);
// Retrieving branch data
uri = this.getUriBefore(uri);
key = this.getKey(uri);
label = this.getLabel(key);
style = STYLE_CLASS_BRANCH;
logger.info("BreadcrumbHandler() getBreadcrumbs [branch] uri=" + uri + " key=" + key + " label=" + label);
if (uri.endsWith(ROOT)) {
notRoot = Boolean.FALSE;
}
}
// Adding home data
String[] bc = new String[3];
uri = URI_HOME;
key = this.getKey(uri);
label = this.getLabel(key);
bc[0] = uri;
bc[1] = label;
bc[2] = STYLE_CLASS_HOME;
logger.info("BreadcrumbHandler() getBreadcrumbs [home] uri=" + uri + " key=" + key + " label=" + label);
breadcrumbs.add(bc);
// Removing link from leaf breadcrumb
breadcrumbs.get(0)[0]="#";
// Reverse breadcrumbs assembly to: home > branch...branch > leaf
Collections.reverse(breadcrumbs);
}
return breadcrumbs;
}

Labels for each view, provided with the resource bundle, like:

TLD.LABEL_LINK_INTERNAL.index=Start
TLD.LABEL_LINK_INTERNAL.company=Unternehmen
TLD.LABEL_LINK_INTERNAL.company.management=Geschäftsleitung
TLD.LABEL_LINK_INTERNAL.company.location=Standort
...
TLD.LABEL_LINK_INTERNAL.index=Home
TLD.LABEL_LINK_INTERNAL.company=Company
TLD.LABEL_LINK_INTERNAL.company.management=Management
TLD.LABEL_LINK_INTERNAL.company.location=Location

The tags in the header template:

<div class="breadcrumb">
<h:form>
<c:forEach var="breadcrumb" items="#{breadcrumbHandler.breadcrumbs}">
<h:link value="#{breadcrumb[1]}"
outcome="#{breadcrumb[0]}"
styleClass="#{breadcrumb[2]}"/>
</c:forEach>
</h:form>
</div>

That’s all.

The clue between a view and its label is the variable part of the label key, that means the part after TLD.LABEL_LINK_INTERNAL, consisting of the viewid.

The label becomes reused for the breadcrumbs, every local link as well as the title of each view.

This works very well and is completely independend of PrettyFaces.

Now I like to include view fragments (the part in the URL after a # sign) into the breadcrumbs too.

So far as I know, there is no way to get a fragment from the viewid itself. So I have to retrieve it from the URL or provide it with the internal link as a parameter.

My question now is, how could I get a fragment from the URL using Rewrite.