Spring clean-up

Even though I liked the theme that I found and customized, I finally got tired of the look of it(and the general dark tone that it had). I’m a very positive and smiling person and having a dark theme like that didn’t really reflect my nature.

I’ve been looking for redesigning my blog for maybe half a year, but due to other more important tasks(work, personal life, etc.) I never got around to it. To be fair me being not very good with the visual arts(yes – I can match a new piece of an UI to the rest of it, but can’t build anything from ground-up) helped delay the change as well.

But then I just decided that it’s time to get a new theme. I went on looking for one and after a quick Google search, I stumbled upon this article at WPMU Dev – 85 Free Clean and Simple WordPress Themes. To be honest I also enjoyed the Landscape theme from that list, but then decided against it, due to it’s dark colors(I assume that would’ve been easy to fix). While not all of the themes in the list would fit my blog, some of them are pretty cool and can be definitely a good fit different types of sites.

In the end I picked Highwind by James Koster(I didn’t get to the bottom of the list – I was too impressed with it). It’s clean, responsive(which my old theme wasn’t) and content-centered. Easily customizable via Header images and the theme Customizer it gives easy access to the main look of the site(basic colors and sidebar position).

The theme is completely free and open-sourced – it can be found on WordPress.org and GitHub. A quick glance of the code tells me that it’s well-organized and seems to be following the WordPress Coding Standards. It’s also written with child-themes in mind, so extending and overwriting it’s functionality with a child theme is a breeze.

Progress on Multilingual WP

Over the last two weeks I didn’t had the chance to actually spend a lot of time working on the plugin, BUT I’m proud to say that 2 very big things happened over those two weeks:

1. Started using the plugin for a big corporate website

At the company I currently work at, we got the task to convert an ASP.NET site to a WordPress site. The site is in two languages and has quite some content – well it probably has around 70 pages in each language and a big load of files as well, but that’s still more than the average website. Since I’ve decided to stay away from qTranslate when it comes to big multilingual websites, I decided to get my plugin for a spin and see if can handle such a website and it’s needs.

While working on the website a bunch of small issues showed up and I was able to resolve them right on the spot. In general I didn’t come across anything serious, which makes me more confident in the (hopefully)upcoming launch of the plugin to the general public

I also stumbled upon a different issue with multilingual websites – sometimes not every page is available in each language. Sometimes you want to display certain content just for specific language/s. Take the following example:

You have a university and on your website you’ve published information about it – including your address, contacts, etc. You’ve also created a page in your native language about the programs/discounts that local students can take advantage of – that is certainly information that is not suitable for foreign exchange students and they don’t need to be bothered to see it on your website. On the other hand you also have a section in foreign languages explaining what you can offer to exchange students – something that the local students won’t benefit from. So you only want to display those pages to their expected audience.

I tweaked here and there and in the end I came up with a custom-tailored solution that involved a simple meta panel displayed on every page/post/etc with a list of check boxes with all enabled languages. When you check a certain language, this page suddenly becomes unavailable for that language – it’s removed from menus, search results, even if you try to open the exact URL it will still display a 404 error. I’m even thinking of adding this functionality as an option to the plugin(it would be disabled by default), but it would probably need some more work.

2. The first website using Multilingual WP has gone live

Well, ok – it’s the second one of which I know, but I’m not counting themoonwatch.com

This is the website for a team that will participate in the Red Bull X-Alps this year. You can check-out their website here – X-Alps – BasqueTeam. The guy who worked on the website is one of the team members – Iñigo Arizaga. He initially contacted me with a couple of bugs regarding the plugin and then kept on doing that as he was finding various small issues while developing the site. He was of great help to me and I really appreciate it I wish them good luck, favourable wind and meteorological conditions and most importantly to enjoy the event!

 

That being said – if anyone else has successfully launched their website using Multilingual WP to make it multilingual – please feel free to drop a link in the comments and let me(and everyone else) know about it.

Migrating to Multilingual WP

After a long time of working on the code of the multilingual plugin, I finally dared to test the plugin in a live environment – my own site!

The migration wasn’t as smooth as I wished it to be, but that was expected – I fixed a bunch of issues that I hadn’t noticed until then. So far the plugin’s development is moving on very well and hopefully I’ll really be able to release it soon(I’m not coming up with a date for when that would happen, simply because things can change a lot in just a week or so).

After adding support for the excellent Google XML Sitemaps plugin(which was the main thing stopping me from trying the plugin on my site) and making the Taxonomy support better I decided to finally upload the plugin to my website and see what happens.

If you decide to do that, please, PLEASE, make a back-up of your database – in my case I didn’t had to use it, but it’s good to have one just in case something goes terribly wrong.

I activated the plugin, configured the desired languages and went through the migration of my posts(which for just two languages turned out to be extremely fast). The migration worked flawlessly and I ended up with both of my languages in the new interface(migrated from qTranslate) – for both posts and pages, and categories and tags.

I decided to use the feature of the plugin, where I can set custom slugs for each taxonomy(besides the custom slugs for each category/tag). It worked sort-of-okay, and I had to fix some bugs with it. The only concern one might have when using this feature on an already set-up site is that old links will break and you’ll have to use a plugin that redirects the broken URL’s to the correct ones. I used the 404 Redirected plugin for that – it’s a bit clumsy and is lacking Regex support, but I only have a handful of links that I need to fix anyway, so it was fine.

In the case of more URL’s, it’d probably be smarter to use a plugin like Redirection – I personally didn’t like it a lot, because it didn’t had the option of disabling automatic redirection to the home page on 404’s, but it does have support for Regex rules, which would make it much more easier to fix more of the broken links with less entries.

Other than that – the language switcher doesn’t come with built-in styling, so as you can see in my sidebar at the moment the text is not properly aligned with the flags – I don’t consider that an important issue, so I’m putting it off for a bit now – I’ll probably find some time one of these days to do that as well.

One more thing I was going to forget – statistics(of sorts) of the plugin’s performance compared to qTranslate – to be honest, most of the numbers are not that low, compared to qTranslate, but my small website wasn’t causing a lot of trouble for qTranslate anyway. I did 2 scans with qTranslate on and 2 scans with Multilingual WP on – one manual and one automatic for each.

I’m posting the results from just the automatic scans, since they seemed to have “caught” and timed more pages than my manual scans(I think the plugin doesn’t always work correctly).

With qTranslate enabled:

WordPress Plugin Profile Report
===========================================
Report date: June 6, 2013
Theme name: Moon Watch
Pages browsed: 3
Avg. load time: 1.8621 sec
Number of plugins: 19
Plugin impact: 82.56% of load time
Avg. plugin time: 1.5373 sec
Avg. core time: 0.1272 sec
Avg. theme time: 0.0281 sec
Avg. mem usage: 137.17 MB
Avg. ticks: 158,059
Avg. db queries : 52.67
Margin of error : 0.1695 sec

Plugin list:
===========================================
P3 (Plugin Performance Profiler) – 0.0017 sec – 0.11%
qTranslate Separate Comments – 0.0451 sec – 2.93%
qTranslate – 0.8806 sec – 57.28%
Other(13 plugins) – 0.6097 sec – 39.68%

Plugin impact with qTranslate

 

With Multilingual WP enabled:

WordPress Plugin Profile Report
===========================================
Report date: June 6, 2013
Theme name: Moon Watch
Pages browsed: 5
Avg. load time: 0.7518 sec
Number of plugins: 18
Plugin impact: 79.91% of load time
Avg. plugin time: 0.6008 sec
Avg. core time: 0.1270 sec
Avg. theme time: 0.0129 sec
Avg. mem usage: 58.95 MB
Avg. ticks: 14,781
Avg. db queries : 82.60
Margin of error : 0.0111 sec

Plugin list:
===========================================
P3 (Plugin Performance Profiler) – 0.0023 sec – 0.38%
Multilingual Wp – 0.1557 sec – 25.92%
Other(16 plugins) – 0.4426 sec – 73.7%

Plugin impact with Multilingual WP

 

These results are pretty rough – since for more consistent results those tests should’ve been done more and for more pages, but I think some of the information they give is pretty obvious and hard to argue with.

I used the P3 (Plugin Performance Profiler) plugin – I really think it’s an awesome tool – I’m not sure how accurate it its, but it does seem pretty good

 

Well, that’s all for now – feel free to try the beta version of the plugin, by downloading it from GitHub, and wish me luck with releasing the plugin publicly soon!

 

Multilingual WordPress

Multilingual WordPress – that’s the name of the WordPress plugin that I’m currently working on. This plugin will let WordPress administrators to create multilingual versions of their site’s contents.

The idea for it was born, after a couple of times when new versions of WordPress were released, qTranslate(that’s the plugin that I’m using for the same purpose while writing this post) was breaking in an all new and exciting way. The author of this plugin unfortunately doesn’t have the possibility to actively support it and therefore, I decided to build a new plugin starting from scratch, but trying to use mainly built-in WordPress functions in order to reach optimum compatibility of future versions of WordPress.

I started the project about the middle of November 2012, but due to the big amounts of work and some personal stuff, I didn’t had the possibility to work on it a lot. Finally in the end of February, I was able to resume my work on the project and I did a somewhat considerable progress

So far the plugin behaves itself fine in a test environment and can do the following things:

  • Support of undefined amount of languages(adding new languages is really easy, but I haven’t tried to see how many one can add)
  • Adding separate content editors(one per language) to any of the selected post-types(pages/posts/etc)
  • Different URL for each language – besides the part that defines the language, each post can have it’s own “slug” for each language – in order to accomplish this if you are using qTranslate, you’d need to also install the “Qtranslage Slug” plugin
  • Different comments for each language(each comment is automatically displayed in the language that it was written in) – again if you’re using qTranslate, you’d need the “qTranslate Separate Comments” plugin
  • Quicktags “qTranslate” style “[ :bg]content in bulgarian[ :en]content in english”, as well as “[ bg]content in bulgarian[ /bg][ en]content in english[ /en]” and “[ mlwp langs=”bg,en”]content in bulgarian and english[ /mlwp]”
  • And other small things

Of course, there is still some time until the plugin is developed and tested well enough in order to be publicly available in the WordPress.org plugin repositories. Until then, if you’re interested in the plugin, you can follow it’s progress on the GitHub repository.

The Wedding Website

Me and Koji currently live in Istanbul – she’s studying in a univeristy here – and since most of the guests for our wedding live in Bulgaria and some live in USA, sending-out invitation cards via the postal services would be somewhat inefficient and slow. So we decided to make web-based invitations. We looked for an already working solution, but we couldn’t find anything that we liked.

Since I’m more-or-less a computer(well mostly WordPress) geek, I decided that we can make a WordPress-based website that would serve as guests and invitations management application.

So then came the design part. Honestly I’m not good at designing a complete product(well I’ve never tried to make a complete design of something, but I’m pretty sure it won’t turn out really good). So we thought about designers that we know and luckily Koji has a friend that makes designs. She was also one of the first people to know that we’re officially getting married. So we asked her if she’d like to design our wedding invitations. She agreed and we sent her a couple of examples of things that we both like with some ideas that we have. A week or so later(she’s been working on the invitation in her spare time, so that was pretty fast and we really appreciate that! ) she sent us the ready design. Once we got it – we just had no words, because it was really really beautiful and we just fell in love with it right away.

Then came my part – since the design was mainly using custom fonts, I only left the dynamic text(like the guest’s name and labels for the answer) actual text and used the rest as couple of separate images. After all I’m not aiming for high rankings in Google with my invitation, so it’s not a big of a deal that I haven’t done it in a SEO-friendly way

After I’ve done the main stuff, I took care of a couple of some small details – for instance I added a loading animation that would stay there until the whole page is loaded and then fade-out and the invitation would fade-in. I also made the response form submit with AJAX, showing a nice message once it’s submitted.

Now since I’m using pretty permalinks, it’s not super hard to guess a guest’s name and see their invitation(therefore response) on their behalf. To battle that, I added a ?n=longstringofseeminglyranomcharacters where longstringofseeminglyranomcharacters is a unique string for each invitation – it’s generated by a long complicated nonce, combined with the post ID of the invitation, which is then hashed using a PHP algorithm. Basically it’s nearly impossible to guess that nonce – it’s more likely that my server will go down because of the too-excessive use of resources than anyone brute-forcing through that.

Basically what happens when an invitation is about to be displayed is that the script checks the n parameter and compares it with the correct one for this invitation. If it’s missing or it’s not correct – the user gets redirected either to the home page, or to an error page(if it’s defined in the site settings) and doesn’t get to see the invitation. Besides the initial idea, this allows to do one more thing – if I change the nonce(which is not visible anywhere on the site and you need to access the code to be able to see it), all of the invitation links will become invalid – that’s useful if you want to have an exact time until invitation responses should be collected.

Here are a couple of screenshots from the invitation itself:

Invitation - loading

Invitation - main

Invitation - response saved

And last, but not least I want to express my gratitude towards Maria – the designer of our invitations

Custom Permalinks for hierarchical taxonomies

The title is pretty vast and non-descriptive, but it sets the general idea of the post. In general the Permalinks system that WordPress uses is pretty flexible, but it also has it’s limitations. Quite recently as I was working on a client’s project, I stumbled upon one of them.

The project was to create a Frequently Asked Questions database, using WordPress. The client wanted the following structure for the database(this is a simplified version)::

  • Index of the database ( http://example.com/faq/ ) [Index of the whole database]
    • Main Category ( http://example.com/faq/category/ ) [Index of the Main Category]
      • Post in the Main Category ( http://example.com/faq/category/post-1-slug/ ) [View only Post 1]
      • Sub-Category ( http://example.com/faq/category/sub-category/ ) [Index of the Sub-Category]
        • Post in the Sub-Category ( http://example.com/faq/category/sub-category/post-2-slug/ ) [View only Post 2]
    • Another Main Category ( http://example.com/faq/another-category/ ) [Index of the other Main Category=]

Everything looks normal(as structure of the URL’s) for the regular user, but WordPress has a different idea on the matter Instead of an URL like http://example.com/faq/category/ we will be able to see the index of the Main Category at an URL like http://example.com/faq-category/category/, which as you can notice is quite different from the initial idea. To fix this issue we have to add a couple of custom Rewrite Rules and functions.

The first step is to register the new Custom Post Type and it’s Custom Taxonomy. Here’s how:

This code registers the new post type and it’s “FAQ Categories” taxonomy, which we will use to categorize the questions.

After we register the new post type, we have to add two functions that will make the Permalinks work the way we want them to:

In the code above we registered two functions – register_faq_rewrite_rules() and fix_faq_subcategory_query().

The first function adds the following rewrite rules:

  • faq/([^/]+)/?$ – this rule will be applied when the URL of the page that is being loaded looks something like “faq/any-character/” – in other words when the URL starts(after the part with the home page URL) with “faq/” followed by any combination of symbols, without “/”( “([^/]+)” ), and possibly followed by a “/”( “/?” ). Also in order to match, this part has to be the last part of the URL(in other words there won’t be a match, if the URL is “faq/any-character/something”).When the current URL matches, the page will display a FAQ Category archive for the category(according to the example I gave) “any-character”.
  • faq/([^/]+)/([^/]+)/?$ – this rule is almost the same as the previous, except for the URL that would match this rule looks like “faq/any-character/post-slug/”.This will display a post with slug “post-slug” from a FAQ Category with slug “any-character” OR an FAQ archive for a FAQ category with a slug “post-slug” that is child of the “any-character” FAQ category.
  • faq/([^/]+)/([^/]+)/page/(\d{1,})/?$ – this rule will match paginated results for a sub-category archive.
  • faq/([^/]+)/([^/]+)/([^/]+)/?$ – this rule is almost the same as the previous, except for the URL that would match this rule looks like “faq/any-character/sub-category/post-slug/”.This will display a post with slug “post-slug” from a FAQ Category with slug “sub-category”.

The second function on the other hand fixes the issue with the sub-categories. The issue itself consists in the fact, that when you try to load a page with URL faq/category/child-category/, WordPress would try to load a post with slug “child-category” instead of the sub-category with slug “child-category”. The function itself is probably not the best solution to the problem, at least because we have to make an additional query to the database, but it’s the only solution I was able to come-up with Since the function checks if there are posts with slug “child-category”, if you happen to have posts(from the FAQ post type) and categories with the same slug, you might get unexpected results

That’s enough to make the FAQ database run properly, but right now if you want to fully use the new Rewrite rules, you’d have to write every URL manually(I mean, when you link to content from the FAQ database). This is because WordPress doesn’t know how to generate the links, so that they match our idea. That’s why we add a couple of more functions:

The above functions “filter” the output from two built-in WordPress functions, which take care of creating the correct URL’s for all pages, posts, taxonomy archives, etc.

There is one more issue, that could be a serious problem for some users – the duplicate content issue. There is a rather large chance, that Google or another search engine that crawls your website to get quite upset by the fact that it can find identical content in two different URL’s(for instance faq-item/post-2-slug/ and faq/category/sub-category/post-2-slug/). This can be avoided with a function that redirects the users to the correct address, but I’ll leave this up to you

If you want to see the whole thing in action, you can go to Custom Permalinks Test.

Change #16

Както споменах в предния пост – “очаквайте още нови неща тея дни”. И ето, че се появи новия панел със бутони за споделяни

Задвижван само и изцяло от CSS3(пак за тези които не ползват браузъри, които да поддържат CSS3 – сори :)), елегантен, не-натрапващ се и в същото време лесно достъпен.

Първоначално смятах да го анимирам с jQuery(JavaScript библиотека), обаче в последствие реших да се възползвам(пък и да проверя) предимствата на CSS3. Оказа се че в общи линии анимациите стават изключително лесно което е голям плюс.

Ето кода който зарежда бутоните:


<div id="mw_custom_sharing"></div>
// функцията която зарежда самите бутони - във functions.php
function render_floating_social_buttons() {
$url = urlencode(curPageURL()); ?&gt; // тук се взима и енкоудва URL-то на сегащната страница
<div id="fb-root"></div>
<script type="text/javascript" src="http://connect.facebook.net/en_US/all.js#xfbml=1"></script>

<div class="alignleft fb-share-btn"><a type="box_count" name="fb_share"></a></div>

&nbsp;

<div class="alignleft google-plusone"></div>

<script type="text/javascript">// <![CDATA[
(function() {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();

// ]]></script>
<a class="twitter-share-button" href="http://twitter.com/share" data-count="vertical">Tweet</a>
<script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script>
<?php }

И съответно CSS-a :

 #mw_custom_sharing { width: 70px; height: 40px; overflow: hidden; padding: 15px 15px 15px 0; position: fixed; left: -75px; top: 130px; z-index: 100; -webkit-border-radius: 0 10px 10px 0; -moz-border-radius: 0 10px 10px 0; border-radius: 0 10px 10px 0; -webkit-transition: all 500ms ease-in-out; -moz-transition: all 500ms ease-in-out; -o-transition: all 500ms ease-in-out; transition: all 500ms ease-in-out; background: url(images/background.gif) repeat 0 0; } #mw_custom_sharing:hover { left: 0; height: auto; min-height: 330px !important; } /* това селектира всички елементи, които са директни наследници на #mw_custom_sharing, и не са script елемент И нямат id="fb-root" */ #mw_custom_sharing --> *:not(script):not(#fb-root) {
padding-bottom: 15px;
margin: 0 auto 15px auto !important;
text-align: center;
border-bottom: 1px solid #ccc;
width: 70px;
display: block;
}
/* за FB Share бутона трябва малко по-специфичен стил, за да се центрира */
#mw_custom_sharing .fb-share-btn .fb_share_count_wrapper { float: none; text-align: center; }

/* Това избира последните два директни наследника на #mw_custom_sharing, които не са script елемент и ...
Селектирам последните два, защото знам че почти винаги последния елемент е script */
body #mw_custom_sharing > :nth-last-child(-n+2):not(script):not(#fb-root) {
padding-bottom: 0 !important;
margin: 0 auto 0 auto !important;
border-bottom: none !important;
} 

Промени бяха направени по следните файлове:

  • header.php
  • functions.php
  • style.css

Линк към ревизията: Цък

A bit of refreshment

Aaaand after moving to the new domain I felt the need(and according to Google Analytics, the visits through the last week have increased a bit ) to make the next set of updates to the theme.

Generally, what visitors will notice are different slight design updates – rounded borders and slim shadows

What you can’t see on the first visit though is that the shadows will change their color according to the time of the day. Basically I’ve divided the day in 4 parts – night(24-6), morning(6-12), day(12-18) and evening(18-24) and each of the parts has a different color for the shadows.

PP: If you are from that percent of the people, that are still using an old browser(IE8 or older, Firefox under 3.5, and I’m not sure about the rest ) there is a pretty big chance, that you won’t see the rounded borders and shadows. If you really don’t see them – just update your browser – at least you will get much better browsing experience

Yellow-Orange Flower

New domain!

And finally I decided to buy another hosting plan + domain(really cheap actually) Unfortunately moonwatch.com is already taken, but I like this one as well

If you try to open a link from the old site, you will end-up in the same page, but on the new site – and this works with literally 18 lines of code :)))

I left the active theme on the old site stripped down to the minimum(index.php – empty, style.css – just the description of the theme, functions.php – only the redirecting function) in order to make the redirection as quick as possible.

The moving of the files themselves was quite quick, thanks to my favourite cPanel, which supports compressing/extracting of archive files. So instead of downloading and then uploading 1000+ files, I just downloaded 1, which I extracted here

Database export, some SQL queries after the import on the new server, and it was like nothing ever happened

So, here is the code for the redirect, and that will be all for this evening

function curPageURL() {
$pageURL = 'http';
if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
$pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
} else {
$pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
}
return $pageURL;
}

function redirect_to_new_domain() {
$requested = curPageURL();
wp_redirect(str_replace('moonwatch.kbsk-titanite.com', 'themoonwatch.com', $requested), 301);
exit;
}
add_action('init', 'redirect_to_new_domain', 1);