Google Translation AJAX API Integration with LinguaPlone
There is no Plone product which translates the content of page into the different language when multi-lingual site is created using the LinguaPlone by the content editor / translator.
So we have created a Plone Product that gives an option to content editor / translator to convert the English content to other languages so they get translated content to start with the conversion of site to another language.
We have used the jquery-translation plug-in (http://code.google.com/p/jquery-translate/ ) to achieve this functionality as there is a limitation of 5000 characters per request in Google AJAX API for translation.
How it works?
It can be installed using the buildout or just copy the product in the ‘products’ folder and restart the Plone.
Go to the Site Setup -> Add-on Products, check this product from the “Products available for install” section and hit Install button to install the product to the specific plone site.
Now go to the any page which you want to translate, select the language from ‘translate into …’ menu as shown below.
After selecting the language one will see the split screen as below with the original content in left and in right side, it will get translated.
After installing the Google Translation product to this site, “translate using google” button will be visible in this LinguaPlone template.
Click on the “translate using google” button to translate the content which is there in the left side.
Translated content is auto filled in the right section for title, description & content fields. You can see in the below screen that content has been translated using the Google AJAX API and populated the respective fields in the right section.
Save the page and now you have the translated page created in few seconds.
How did we create Google Translation Plone Product?
- Create your Plone 3 Theme product folder structure using the Paster command or you can use this website to create one http://paster.joelburton.com/.
- If you use the paster.joelburton.com then here are the values you can fill to create product.
Click on the Generate button to create the product, it will display the links to download the created product as zip or tarball.
Download and unzip it, you will have the following folder hierarchy.
- Copy the “translate_item.cpt” & “translate_item.cpt.metadata” file from the LinguaPlone product installed on your PC, these files are located in the LinguaPlone -> Skins ->LinguaPlone folder.
- Paste these files in the “GooleTranslationApp_Products_custom_templates” folder.
- Create a folder “GooleTranslationApp_Products_jsscript” in the skins folder.
- Download jquery-translation plug-in and put it in the “GooleTranslationApp_Products_jsscript” folder
- You also need to install the collective.js.jquery plone product as jquery-translate plug-in requires the jquery 1.3.2 version.
- Now open the translate_item.cpt file in any text editor and paste the following line whenever you want to display the ‘translation using google’ button on the LinguaPlone translation page.
<input class=”context” onclick=”translate();return false” value=”Translate using Google” />
- Create a blank js file googletranslation.js in the “GooleTranslationApp_Products_jsscript” folder.
- Open this file in the text editor and paste the script below which actually translate the content into other language using the Google AJAX API.
function translate()
{
var fromLang = ‘en’;
var toLang = ‘en’;
var fromLangCol = document.getElementsByName(‘lp_translating_from’);
if(fromLangCol.length > 0)
fromLang = fromLangCol[0].options[fromLangCol[0].selectedIndex].value;
var toLangCol = document.getElementsByName(‘lp_translating_to’);
if(toLangCol.length > 0)
toLang = toLangCol[0].options[toLangCol[0].selectedIndex].value;
startTranslation(fromLang, toLang, ‘parent-fieldname-title’, ‘title’);
startTranslation(fromLang, toLang, ‘parent-fieldname-description’, ‘description’);
startTranslation(fromLang, toLang, ‘parent-fieldname-text’, ‘content’);
}
function startTranslation(srcLang, targetLang, srcId, targetId)
{
var sourceText = ($(‘#’+srcId)[0]).innerHTML;
if($.trim(sourceText) == ”)
return;
$.translate(sourceText,srcLang,targetLang, {
start: function(){ },
complete: function(translation){
var objControl = ($(‘#’+targetId)[0]);
if(objControl == null && window.kupu)
{
editor = window.kupu
editor.resumeEditing();
var obj = document.createElement(“DIV”);
obj.innerHTML = translation;
newtext = editor.getInnerDocument().firstChild.appendChild(obj);
editor.insertNodeAtSelection(newtext)
editor.updateState();
}
else if(objControl == null && window.FCKeditorAPI)
{
FCKeditorAPI.GetInstance(“text”).SetHTML(translation);
}
else
$(‘#’+targetId).val (translation);
},
error: function(){ }
});
}
- Open the skins.xml file from the Products -> GoogleTranslationApp -> profiles -> default folder and add the information about the new folder we have created in the skins folder as below.
xml version=”1.0″?>
<object allow_any=”False” cookie_persistence=”False”
default_skin=”google_translation”>
<object name=”GooleTranslationApp_Products_custom_images”
meta_type=”Filesystem Directory View”
directory=”GooleTranslationApp.Products:skins/GooleTranslationApp_Products_custom_images”/>
<object name=”GooleTranslationApp_Products_custom_templates”
meta_type=”Filesystem Directory View”
directory=”GooleTranslationApp.Products:skins/GooleTranslationApp_Products_custom_templates”/>
<object name=”GooleTranslationApp_Products_styles”
meta_type=”Filesystem Directory View”
directory=”GooleTranslationApp.Products:skins/GooleTranslationApp_Products_styles”/>
<object
meta_type=”Filesystem Directory View”
directory=”GooleTranslationApp.Products:skins/GooleTranslationApp_Products_jsscript”/>
<skin-path name=”google_translation” based-on=”Plone Default”>
<layer name=”GooleTranslationApp_Products_custom_images”
insert-after=”custom”/>
<layer name=”GooleTranslationApp_Products_custom_templates”
insert-after=”GooleTranslationApp_Products_custom_images”/>
<layer name=”GooleTranslationApp_Products_styles”
insert-after=”GooleTranslationApp_Products_custom_templates”/>
<layer name=”GooleTranslationApp_Products_jsscript”
insert-after=”GooleTranslationApp_Products_styles”/>
</skin-path>
</object>
- Open the skins.zcml file located in the products folder and add the lines in bold below.
<configure
xmlns=”http://namespaces.zope.org/zope”
xmlns:cmf=”http://namespaces.zope.org/cmf”
i18n_domain=”GooleTranslationApp.Products”>
<!– File System Directory Views registration –>
<cmf:registerDirectory
name=”GooleTranslationApp_Products_custom_images”/>
<cmf:registerDirectory
name=”GooleTranslationApp_Products_custom_templates”/>
<cmf:registerDirectory
name=”GooleTranslationApp_Products_styles”/>
registerDirectory
name=”GooleTranslationApp_Products_jsscript”/>
</configure>
- Open the jsregistry.xml from the profile -> default folder and add the following content to register the googletranslation.js file
<?xml version=”1.0″?>
<object>
<javascript cacheable=”True”
compression=”safe”
cookable=”True”
enabled=”True”
expression=”not: portal/portal_membership/isAnonymousUser”
id=”jquery_translate.js”
inline=”False”/>
</object>
- Now all is done. Just put the complete package in the src folder of your Plone installation directory. Add the path in the buildout.cfg to install this product and restart the Plone.
You can follow the steps given in the starting of this article on how to use this product to see it working.
Code generator for rapid application development
In today’s era most of the software companies are approaching towards rapid application development methodology for software development.
First question which arises in everyone’s mind that why do we need code generator?
- To better concentrate on business logic rather than writing lots of code.
- To achieve better quality as there will be no defects which are getting introduced into the application code by software developers.
- To have a consistent architectural approach as there will not be a typo mistake, different types of variable declaration etc. which are getting introduced while number of developers are working on same software.
- It will decrease the time span of the software development process with less number of resources.
Code generator was designed by me to have all of these fruitful benefits with a consistent code generation approach. Code Generator was developed as a web application so that it can be hosted at one place and several developers can use it at the same time and at different locations. User has to customize the settings according to their projects and destination folders can be specified according to their project folder structures.
Code generator was designed to generate the code for projects which are operating under different layers to have modularization and consistent architecture. Stored procedures can also be generated using code generator to reduce the efforts of software developers so that they can purely concentrate on the business logic of the application.
There are so many tools which are available in the market to generate the code but they take a lot of time to customize them for particular needs and the architecture of the project. Maximum tools in the market which are available were developed as a desktop application. So if you will deploy it at a remote location then only one developer can access it at the same time and if you have to deploy it on different machines of software developers then you also have to maintain version updates in the generator at every developer’s machine which is a big problem.
Please keep reading my blog, i will elaborate it in my next post very soon.
Debugging Assembly Loading Failures
There are situations sometimes when .NET loads wrong assembly or can’t load one at all. Usually we can see “Could not load file or assembly” in that case.
In one of my project we had a situation that gave a real world example for post I was thinking about quite long time. There was a reference of enterprise library in the project and everything worked fine in local & production environment. But one day due to the power problem, production server was rebooted and system stopped picking assembly of enterprise library. There can be many situations like that, when in our opinion all is perfect but isn’t and .NET fails with loading assembly or loads incorrect one.
.Net framework has given a wonderful tool “Fusion – Assembly Binding Log” to diagnose such problems. If you will take a look into .NET Framework directory you will see a fusion.dll. This inconspicuous file is responsible for finding locating the correct assembly and, what is more important, can produce a log of that. As a pair for that we have simple tool named fuslogvw.exe that can be found in Visual Studio directory. This small tool is an Assembly Binding Log Viewer and is able to get logs created by fusion.dll, save them on disk and of course display.
Turning on Fusion Logging
Type “Fusion” in the Start Menu. The Assembly Binding Log Viewer, or “Fusion Log Viewer” which will tell the CLR to load assembling binding/loading activities to a folder, then let you see them. Be sure to run it as Administrator if you want to change the Settings, otherwise they’ll be grayed out. Alternatively, just set the Registry keys your self. (I just memorized them, as I set them all the time.) Set HKLM\Software\Microsoft\Fusion\ForceLog registry value to 1 and HKLM\Software\Microsoft\Fusion\LogPath registry value to C:\FusionLogs or some path that exists.
Now you can run code/program that causes the problem and click Refresh when it will finish. You should see a log file on the path specified for fusion logs. Double click on any log entry will open whole log for that assembly. Information you can find there is sometimes amazing. By analyzing that information you should be able to find the problem and don’t forget to turn logging of when you finish.
Plone – An Amazing CMS
Plone (http://plone.org/ ), a Python based Content Management System (CMS) built on top of the open source application server Zope, is one of the best Open Source CMS among paid & open source CMS available.
One of its great feature is, it allows you to write Python script / create templates / any customization thru the web (TTW ) & run instantly.
You can never lose you changes as it maintains the complete history of changes and you can compare the differences among different versions online.
Another cool feature is you can write the rules for any content type when it is created/update/delete/moved/copies etc using the Rules Engines to manage your content or initiate any approval workflow etc.
Some of its nice features are as below:
Authentication & Authorization
Flexible Authentication back-end, can be integrated with LDAP / Active Directory or any other source
Security
Users, groups & permission management
Live Search
Multi-lingual support
Content Publishing
Workflow
Caching
SEO URLs
RSS Feed
Commenting on any content type
Moderation
Page / Content Templates
Drag & Drop Re-ordering of content
Multiple Views of content type
Automatic image scaling and thumbnail generation
Rich ecosystem of free add-on products
Cross-Platform
Inline Editing Support
Cut / Copy / Page Operation support on content
Collaboration and sharing
Versioning, history and reverting content
Full Text Search on documents like Word / PDF
Collections
Automatic Sitemap Generation
Rules engine for Content
Custom Forms
Portlets like Calendar / RSS Feed / Search etc.
Themes
Customization
Connection to external databases
There is a long list of functionalities.
Many other features can be added to Plone by deploying & Installing the Add-on products like Blogs/ Forums etc . You can create your own add-own product and deploy.
Create OpenXML Packaging API for .NET 1.1 & .NET 2.0 – Part 1
The adoption of XML (Zipped) as the native file format for Word/Excel/PowerPoint 2007 has opened up a new set of opportunities for software developers to integrate & generate Office files across the platform. There is absolutely no need to use OLE Automation etc in VB or .NET.
Microsoft System.IO.Packaging comes with .NET 3.0.
About Open XML
Open XML is a file format for representing Microsoft Office documents like word spreadsheets and presentations documents. An OpenXML document file contains mainly XML based files compressed within a zip package.
You can read more about OpenXML formats here: http://msdn.microsoft.com/en-us/library/aa338205.aspx
It is important to have knowledge of Open XML file formats, its structure, about Parts & Relationships and content types to understand this series of article.
Sometimes there are requirement to generate the office files in the software application which is based on .Net 1.1 & .Net 2.0. It cannot be upgraded to .Net 3.0/3.5 because of some internal reasons so it is necessary to build the Packing API which can work with .Net 1.1 & .Net 2.0 so that .docx, .xlsx & .pptx can be created from their system.
This article will be in parts, in part one we will define the interfaces required to build the Packing Library.
An Office file (excel, work, ppt) is a zipped file that contains the folders, xml, images etc. which is called as package and a package can have multiple element which are called PackagePart like Image, comment, notes, header, footer, chart, slide, worksheet & many more.
There is hierarchy of parts and they are related to each other. This relationship is maintained in .rels file inside _rels folder.
Content Type information like xml, text, image, mp3, wav is also stored inside the ZIP Office Package in the Content_Types.xml file.
So based on the structure of Office File Format we can define the following abstract / inherited classes
/// <summary>
/// Abstract Package Class – It represents an office 2007 document (Excel / Word / PPT)
/// </summary>
public abstract class Package
{
}
/// <summary>
/// Abstract PackagePart Class – Holds in the information for a Package Part like Header, Footer, Hyperlink, Image, Chart etc.
/// </summary>
public abstract class PackagePart
{
}
/// <summary>
/// PackageProperties Class – To store the Package core & other Properties like
/// </summary>
public class PackageProperties
{
}
/// <summary>
/// PackageRelationship Class – Stores all relationships
/// </summary>
public partial class PackageRelationship
{
}
/// <summary>
/// ZipPackage Class: Implementation of Package Class.
/// </summary>
public class ZipPackage : Package
{
}
/// <summary>
/// ZipPackagePart Class – Implementation Class for PackagePart
/// </summary>
public class ZipPackagePart : PackagePart
{
}
Package & PackagePart can have multiple implementations based on which ZIP Library you use to zip/unzip your package file.
Gmail Mobile API – how to log out
If you are trying to use gmail mobile API to create a light weight JavaScript based gmail application by posting requests to https://mail.google.com/mail/m/12345, it saves login info in cookies…
To logout and login again from some other user you need to logout first by deleting the existing cookie, something like this:
netscape.security.PrivilegeManager.enablePrivilege(“UniversalXPConnect”);
var cookieMgr = Components.classes["@mozilla.org/cookiemanager;1"].getService();
cookieMgr = cookieMgr.QueryInterface(Components.interfaces.nsICookieManager);
cookieMgr.remove(“mail.google.com”, “S”, “/mail”, false);
cookieMgr.remove(“mail.google.com”, “GMAIL_AT”, “/mail”, false);
cookieMgr.remove(“.mail.google.com”, “GX”, “/mail”, false);
S M Macario keeps increasing customer base even during slowdown
We are able to make some good progress during the slowdown period; it could be because of our belief in our vision and the quality of the work being done by our team.
We have entered in manufacturing (fashion), and health-care adding to our existing list of industries.





