Sunday, July 14, 2013

So came functionality

The brief update:
It makes me very sad that all my work for this week can be put in one sentence: "You can vote translations and submit translations now". There it is, all of it in one sentence.

Guidelines and Progress bar

As I added stuff to the plugin I became aware that it might cause confusion, so I added guidelines into the mix. It is a link next to the plugin name and will basically just show a static list of what I think are important instructions.
The other thing, not really necessary is the progress bar. The red-ish thing under the language name. I thought it would be nice to see how much of the language is translated. Since this is a clean start the progress bar is all red but it could look something like this (in the future)



There are a few other visual tweaks to the plugin but those are related to the functionality while this is purely for the appearance so they will be presented bellow.

Not visible code changes

I have cleaned up the code a bit. For one I realized that the creation of the translation form is getting too 'heavy' for the JS. So this part is moved to a PHP script. Additionally the code is a bit updated to improve performance and ease further data manipulation. Some of the files are moved from the Plugin folder to the Public_HTML folder. I changed the JS code for the form slider. Now it uses a bit more jQuery (which means that it also works much better) One problem still persists, I can't seem to get the $_TABLE['translations'] syntax to get working. This is another beautiful feature of Geeklog. It will allow the CMS user to add prefixes to their tables and developers can then refer to their tables using the Geeklog interface, I probably missed something there and fixing this is on the top of my 'to do' list.
However the plugin went from 1 table up to 3. 1 table for the translations. 1 table for formatted original language strings where Don't have an account yet?  Sign up as a <a href=\"{$_CONF['site_url']}/users.php?mode=new\" rel=\"nofollow\">New User</a> will be saved as Don't have an account yet?  Sign up as a <tag>New User<tag> , the <tag> values will also be saved as a JSON object, and of course the variables inside the tags will be saved - {"html":["<a href=\\\"{VAR}\/users.php?mode=new\\\" rel=\\\"nofollow\\\">","<\/a>"],"vars":["$_CONF['site_url']"]}.
Later on when the assembling of the new language file is done these values will be moved back to their strings. Finally the last table is for votes.

Submitting translations

A faulty input

As we are talking about translations here there is no way (at least  I have not figured out any jet) to validate the user input. It literally can be anything, except in the case of translating strings such as Comments (<var>).  These the plugin will validate. Again in some cases the language grammar might be different so the actual place of the <var> will not be the same, but what I can do is count the occurrences of <var> and <tag> pseudo tags. It looks something like this:


After trying to submit this the user would get a warning. If for example I try to submit a'faw  as a translation for Comments (<var>) I will get an error. (According to VLD a'faw is Vulcan for  comment)


The first part of the 'message' is at the beginning of the form. Indicating that there has been an error, what the error is and in which place(es).
If there had been valid inputs those would have been processed regardless of the faulty one. This could look as such: 
In the second case the successful translation is processed and the input box is removed, the faulty input is marked. The phrase postì säplltxevi is Na'vi for Post a comment at least according to these guys.
If you wonder why the progress bar did not change - I just submitted 1 translation (as can bee seen in the plugin interface) the Geeklog language arrays have around 1700 strings in total and the rounding is done on 2 decimal places.

Voting

The voting interface has been show last week. It is basically 2 buttons next to the proposed translation.
Now the voting actually works. As proposed by +Dirk Haun the vote can be changed.
If another user now came to the same page they could see my translation (in the general case the translation with the most up votes is shown). As the user did not vote on this translation jet the vote buttons both have reduced opacity. However as soon as the user does vote on the translation the vote he gave will be highlighted. The new user can also submit their own translation. In any case if a translation reaches a certain number of negative votes the translation is removed from the database. Currently I have set this limit to be a vote count of -5. (every up vote increases the value of vote count by 1, every negative decreases it by 1)


In summary I think the hardest part of the project is done. That was building this interface, not because building a HTML form is a hard task but finding the correct strings on the page was hard. Especially if you try not to be intrusive on the original code base and dare I say this I have done. Geeklog developers will not ever have to worry about the plugin, except in one case: when adding to the language files, an array element has to be in exactly one line.


Not related

I finally got the pictures from my presentation, here is one. I had some feedback and it seems my future colleagues liked what I had to say.


Friday, July 5, 2013

The plugin is getting in shape

It has been a while since the last post. Somehow I had the feeling there is not much to report. However when I take a look at the changeset on my repro I see that there has been work done, a lot of it. It is kind of hard to be objective about this. What may seem to be only one little feature can require a lot of coding, planing a bit of crying... This project is very special this way as the most part is not adding code, but finding less ugly ways to solve problems. +Dirk Haun said "There is no beautiful way to do this".

The big bad language file

So lets start, since the last blog post I have changed the language_markup.php file, the file that marks the core Geeklog strings I have to identify on the page later on. In addition to the actual markup it will now take all the strings, edit them and save them to the database. This has been done mainly because some of those strings have PHP variables, html code and so on and so forth. All of those are replaced with pseudo tags such as <tag> and <var> so the final display for the translator is Comments (<var>) , the user is required to type the <var> code in the translation, in the appropriate place. Say a translation to Swahili would be Maoni (<var>) (I used Google Translate for the example). Later on, when we do the 'packing' of the translations the <var> and <tag> will be replaced with whatever variable, or HTML was original there.


This is how the string looks inside the database:
englishcoreLANG0159"Don't have an account yet?  Sign up as a <tag>New...{"html":["<a href=\\\"{VAR}\/users.php?mode=new\\\" rel=\\\"nofollow\\\">","<\/a>"],"vars":["$_CONF['site_url']"]}
And the original string from Geeklogs language file:
"Don't have an account yet?  Sign up as a <a href=\"{$_CONF['site_url']}/users.php?mode=new\" rel=\"nofollow\">New User</a>"

It might very well be that this approach will need some editing. As currently I treat all the language files as text files, read them line by line and edit them as strings. I do this to prevent the PHP variables to display the variable value instead of the variable name.

After I had something which could be translated, and a way to identify the Geeklog core strings on a fully rendered HTML page, it was time to add the user interface.


User interface

The user interface is written in 2 places. Geeklog has it's API for adding content to the sides of the page (where this plugin is located). In this place I only add the core of the interface. In my case this is the name of the plugin, and a <form> in which the user should type the language to which he/she is translating.
Everything else is (and has to be) added from the JS file. The content has to be created dynamically.

Picking the language

To prevent creating languages such as Engrish or Geraman (English and German) I have use jQueryUI to add autocomplete to the input field. This is more or less how the whole thing looks like when you open the page (start a new session).
 
Selecting the language
You may have noticed that the language in the image is test_language_name, this is the language I used in the database. The auto complete is generated from the languages shipped with Geeklog and all the languages submitted previously to the plugin.

After the user has selected his language of choice the plugin will save it as a Cookie, this way the user has to (but is not bound to) select the language only once. The selection can be changed.
 
Changing the language will present the user with the same <form> as if he never picked a language before.

The Translation Form

After the language is picked the actual translation form is generated by JavaScript. Actually most of the preparations are done before the language is selected. The AJAX call to get all the formatted strings from the database is done when the page is loaded. Now the data is 'just' used to create the form and all it's goodies.
The form has 4 basic parts :

1) Highlighter (and remover)
2) Input field
3) Display of previous translation
4) Votes

The highlighter allows the user to identify the string they are translating on the page. Originally I used a onclick() function to highlight the string and onblur() to remove the highlight, but more often then not the user 
would have to scroll to see the highlighted string, which can produce a on blur (unless they use the browser's scroll bar) and the highlight would be lost. So now it is handled via button click.This also allows for multiple strings to be highlighted.

The script will get translations for previously translated strings. It will select the one with the largest 'like' (up vote) value. And display it to the user, the user can then either like or dislike the translation or add his/her own to it. The plan is to pack the translations with the largest up votes, and to periodically (before packing) remove translations with a certain negative vote value. 


Another 'problem' was deciding on which strings to show. As you can guess there are a lot and I mean a lot of Geeklog strings on the page. Showing all of them would reduce the user experience for the rest of the page. As they would, for example, have to scroll a lot just to log off. So instead of making some complicated algorithm to decide upon which 5 or 10 strings to show in the form, I decided to make my own little scroll function. Which looks like on the picture bellow.



Loosely related

My university hosed Summer school of innovation-GeekFEST2013, as one of the students who participated in the Sarajevo Startup weekend and one of the better students of the Computer Science and Engineering  departement I was called to tell them about my projects, the startup weekend and how it is to be a CS student in general. Being the Google fanboy I am I used the oportunity to promote Google Summer of Code, Android Developer Challenge, Android Camp and Summer Trainee Engineering Program (STEP). As well as the idea of contributing to open source/free software projects, and the mutual benefits of doing so.



Monday, June 24, 2013

Big decisions

This has been the first week of coding, officially. And it has been a surprisingly tough one. One of the major design decisions has been made, I have a somewhat bigger understanding of Geeklog plugin development and I feel a slight sense of accomplishment.


Baby steps
The first thing was to make something, a good place to start (if you are interested in making a plugin for Geeklog) is here. This is a detailed handbook. If however you are like me and like to see things examining the plugins which ship with Geeklog is a good approach. I use the Polls plugin as my reference as it has most resemblance with what I am doing. Last but definitely not least, the thing that gave me a kick start is the Plugin Toolkit. It is useful, after providing some basic data about your plugin it will generate a lot of code for you. After that you have to divide the generated files to the right places and of course edit what you need. Again it is a good start it will not develop a plugin.

So what I did was use the plugin to generate some files. After that things went south for a bit. First of all was the decision on who is allowed to do translations. The community decided that logged in users, with credentials provided by the central Geeklog "page" would be allowed to translate. This discusion also included a discussion about how the database should look like and well the final form is as suggested by Wim Niemans. Creating a database table with Geeklog is as simple as editing a sql file (a sample file is generated by the toolkit).
After that I played a bit with the configuration. It is not final it is not even a large step towards the final it was more a exercise for me than providing actual code. But after doing it I am ready to do some real damage when I get to that part. My approach so far was to build simple parts, working good enough to allow me to tackle what I though would be the "big" problem.... And a big problem it was.

The big bad LANG
Before I get to the problem, let me describe how Geeklog core works.
Geeklog has it's language folder with language files, e.g. english.php, bosnian.php, german.php...
A snipet from the english.php file:
$LANG01 = array(
    1 => 'Contributed by:',
    2 => 'read more',
    3 => 'comments',
    4 => 'Edit',
    5 => '',
    6 => '',
    7 => '',
    8 => '',
    9 => 'Admin Functions:',
    10 => 'Submissions',
    11 => 'Stories',
    12 => 'Blocks',
    13 => 'Topics',
    14 => '',
    15 => '',
    16 => '',
    17 => 'Users',
    18 => 'SQL Query',
    19 => 'Log Out',
    20 => 'User Information:',
    21 => 'Username',
    22 => 'User ID',
    23 => 'Security Level',
    24 => 'Anonymous',
...

There are a lot more arrays with a lot more element. The elements can be one word elements or multiple sentences. They can include html code and so forth and so on. They also include common words such as "Save" which can be otherwise included in the page, as a user comment, as a page generated by the static pages plugin... So the big problem is identifying the strings on a rendered page. This is important as the whole goal of the plugin is to provide a context for the translation.

There were several possibilities for solving this. My first idea was to add HTML tags to the array elements such as <span class="translator">.....</span> but the problem with this was that these spans can not be included in places such as the <title></title> or inside a <input value="">. Another approach was to add a API to Geeklog, although this would probably work perfect, and without much hiccups I wanted to avoid doing changes to the Geeklog core.

My (currently) final solution
I went on with the idea of adding some kind of identification to the array elements. Spent some time trying out special HTML symbols such as &#8204. This symbol is invisible for the user, which made it perfect it also was invisible to JavaScript which made it useless.
So I moved on to adding simple text. What I finally have is that all the elements (in the default language file) have these marks: _-start_ and _-end_. I tried to devise something unlikely to appear otherwise on the page.
This change is done when the plugin is installed and is removed if and when the plugin is removed. It will (in the near future) also provide a way to add the identification to other language files (if by some chance the default language of the page is changed).
After doing this, in order to save computation time later I also added data on which array and which element the current string belongs to.
The english.php file now looks like this:
$LANG01 = array(
    1 => '_-start_||array=$LANG01index=1||Contributed by:_-end_',
    2 => '_-start_||array=$LANG01index=2||read more_-end_',
    3 => '_-start_||array=$LANG01index=3||comments_-end_',
    4 => '_-start_||array=$LANG01index=4||Edit_-end_',
    5 => '',
    6 => '',
    7 => '',
    8 => '',
    9 => '_-start_||array=$LANG01index=9||Admin Functions:_-end_',
    10 => '_-start_||array=$LANG01index=10||Submissions_-end_',
    11 => '_-start_||array=$LANG01index=11||Stories_-end_',
    12 => '_-start_||array=$LANG01index=12||Blocks_-end_',
    13 => '_-start_||array=$LANG01index=13||Topics_-end_',
    14 => '',
    15 => '',
    16 => '',
    17 => '_-start_||array=$LANG01index=17||Users_-end_',
    18 => '_-start_||array=$LANG01index=18||SQL Query_-end_',
    19 => '_-start_||array=$LANG01index=19||Log Out_-end_',
    20 => '_-start_||array=$LANG01index=20||User Information:_-end_',
    21 => '_-start_||array=$LANG01index=21||Username_-end_',
    22 => '_-start_||array=$LANG01index=22||User ID_-end_',
    23 => '_-start_||array=$LANG01index=23||Security Level_-end_',
    24 => '_-start_||array=$LANG01index=24||Anonymous_-end_',
...

I am not saying that this is the best possible solution. I am saying that it works and it does not demand changing the coding style of Geeklog. If you have a better solution leave a comment, write me an email, write an email to Geeklog-Devel mailing list...

Doing just this (of-course) makes the page ugly, very ugly.
About this much:




That is why I added some JavaScript magic, to remove the marks and to extract the data I will need to create the translation interface.

This is a sample object I get:
string: Advanced Search, array: $LANG01, index: 75

And this is how the page looks after JavaScript:


Note that not all the strings will be red all the time. The plan is that the user can pick the string he wants to translate and that the picked string will be highlighted. The highlight might be changing the color, or increasing the font size or all of it.

That is the big step I made towards completing this project.

Again If you have any suggestions please feel free to contact me.

For the Geeklog community: You Rock!!! And thank you for having patience with me.

Thanks for reading.

Sunday, June 9, 2013

Just before KickOff

This blog is the place  I will use to gradually report what I have done during the summer. While I will probably skip information about my lunch I will post on the progress of my Google Summer of Code project.

Lets start with a nice introduction on the organization. I think the official website has a better intro than I could write so:
"Geeklog is an open source application for managing dynamic web content. It is written in PHP and supports MySQL, PostgreSQL, or MS SQL as the database backend.

"Out of the box", Geeklog is a CMS, or a blog engine with support for comments,trackbacks, multiple syndication formats, spam protection, and all the other vital features of such a system.

The core Geeklog distribution can easily be extended by the many community developed plugins and other add-ons to radically alter its functionality. Available plugins include forums, image galleries, and many more."


Geeklog sadly did not get into GSoC officialy this year, but thanks to The Fedora Project they still got one spot. Which btw makes me feel a whole lot of pressure.

"Fedora is a fast, stable, and powerful operating system for everyday use built by a worldwide community of friends. It's completely free to use, study, and share."

There is a lot more to learn about both Fedora and Geeklog that I copied here, and I would encourage You to do so.

I hope that the next blog entry will contain more blocks of code than words, but this is the community bounding period, in which to be honest I did not offer my best performance. In my defense however it is the Final exam period on my university and I did have 4 exams in 4 days,with one more pending.

Well I did not write a whole lot but I have been reading the mailing list, actually several of them. What I have learned is that the Geeklog community is really great and patient. And as this project does frighten me from time to time the patient part is very important. After all we, or I am a student,bound to make a few mistakes now and there. Not to broadcast the wrong idea here, I do have cold feet but I am looking forward to having a lot of fun, learning and hopefully producing a great plugin this summer.

My project
In one sentence: "A plug-in for the Geeklog CMS which would enable users to submit translations".
A really detailed explanation of the project is inside my proposal.
It will try to build a plug-in which will allow the CMS users to do translations for the CMS. It should help maintain and improve the current 30+ translations Geeklog's UI has and add some new ones to the mix.
It will also allow users to make their own, private translation, I am not sure how much Geeklog would use this but if You want you would be able to go ahead do a translation to say Vulcan.

What I did so far
I am laying down the groundwork, under the guidance of Dirk Haun, the mobile presenter .
First I got my very own code repository, which I look forward to filling. Then I had to get down with the basics of Mercurial. To make my life a bit easier I decided to use TortoiseHg for as a interaction tool with the repo.
The next step for me was to make sure  I have all the right tools on all the OS running on my laptop. OK that sounded a bit ambiguous, I have 3 systems so it is not quite the hard work but still...

I got done some reading on the Geeklog wiki, and probably will do a lot more. But If You are new to Geeklog and think it is worth Your time this might be a good place to start.

During the day, or tomorrow I will go ahead and make my own minimal plugin, probably something easy and funny just to get started. (Change all the occurrences of "CMS" on a page to "sandwich" ?)

So my setup for the summer is Windows 7/Ubuntu 12.04.02/Fedora 18 with Wamp/Xampp and sublime text 2. And of course Google for when I hit a great brick wall.


Again looking forward to a great summer. And I hope to justify the trust I got from Geeklog.


Unrelated stuff
I don't remember this happening last year but this year the GSoC mailing list got a thread about unsatisfied students. While I do understand the need for feedback and the unpleasantness of not getting accepted I do think I it is not the best thing to publicly write about how the chosen student sucks in comparison to the rejected. (No I have not been mentioned but still..) I do not claim to know on what the exact selection procedure is,but logic implies that the org will pick someone they see more fit to complete the job-given it is in the org's interest to have the job done.