Err the Blog Atom Feed Icon
Err the Blog
Rubyisms and Railities
  • “Ya Talkin' Gibberish”
    – Chris on May 08, 2007

    Advertisement

    Oh man! Just tonight Beast Edge was graced with localization, courtesy of Gibberish. Relevant commits are here and here. There’s already some heated debate on the Mephisto mailing list regarding this change and possible future changes, if you’re into that sort of thing. Dig in.

    Gibba-what-now?

    Yeah, what? Gibberish is a simple Rails localization plugin we developed for FamUpdate and have been slipping into other projects. We’ve got Globalize and we’ve got Localize, but come on. They’re great, and useful, but sometimes you just want something light weight. I know I do.

    I also know keying my translations by a string is not fun. What if I want to change a comma? Or add an exclamation point! Oh, use a symbol. But symbols make it hard to read my views. There must be a middle ground.

    Of course: Gibberish.

    Keyin’

    <%= 'Description'[:description_title] %>
    

    The above will return Description by default. If you’ve another language selected (besides English), it will find the description_title key in that language’s translation file and return the corresponding string instead. Simple.

    You may leave the brackets blank, which will force Gibberish to assume the key is a lowercase, underscore’d version of the string.

    So this:
    "Header description"[]
    
    Is the same as this:
    "Header description"[:header_description]
    

    Real smooth (thanks to technoweenie). Just, be careful. If you change the string too much you could land yourself in the same place we’re trying to escape from. (Trouble.)

    klingon.yml

    Translation files are simple YAML. For instance, es.yml:

    welcome_friend: ¡Recepción, amigo!
    welcome_user: ¡Recepción, {user}!
    love_rails: Amo los carriles.
    

    Something like “Welcome friend”[] will, when the language is set to :es, return ¡Recepción, amigo!. You can change the language quite easily:

    >> Gibberish.current_language = :es
    => :es
    

    It’s even got one of those trendy around_filters:

    class ApplicationController < ActionController::Base
      around_filter :set_language
    
    private
      def set_language
        Gibberish.use_language(session[:language]) { yield }
      end
    end
    

    No big deal.

    Check the languages you’ve loaded with languages:

    >> Gibberish.languages
    => [:es, :fr, :de, :kl]
    

    In dev mode languages are automatically reloaded. From where? RAILS_ROOT + ’/langs’. Gibberish’ll look for .yml files in that directory.

    The above example, we can safely assume, is run within a Rails app with lang/es.yml, lang/fr.yml, lang/de.yml, and lang/kl.yml. Add another language file and it’ll get picked up on the fly.

    Intersomethinglation

    The other cool thing Gibberish provides is interpolation. You may have noticed the {user} in welcome_user way above. Yeah, that’s gonna change.

    Like this:
    >> "Welcome, {user}"[:welcome_user, current_user.name]
    => "Welcome, Chris" 
    

    The {user} bit will be replaced with current_user.name when being rendered. Works for translations, too. Naturally.

    Curly brace’d strings are interpolated in the order arguments are passed. The fact that it says user is irrelevant. Really, it’s only to make things easy to remember. The important part is that it’s the first interpolation bullseye in the string.

    Another example (ostensibly to drill home the point but realistically because me and PJ are on a Sandman kick):

    >> "{name} is from {place}"[:hey_place, 'Chris', 'the Dreamworld']
    => "Chris is from the Dreamworld" 
    

    Okay, you got the idea.

    Grab it!

    From the svn:

    $ cd vendor/plugins
    $ piston import svn://errtheblog.com/svn/plugins/gibberish
    

    Follow trac: http://require.errtheblog.com/plugins/browser/gibberish

    View the README: http://require.errtheblog.com/plugins/browser/gibberish

    And, as always, report bugs to Lighthouse: http://err.lighthouseapp.com/projects/466-plugins

    Enjoy ya jive talkin’ Gibberish. Patches gladly accepted.

  • evan, about 2 hours later:

    What about auto-generating keyed YAML for new languages? Or a test helper that autotested every key in the app for a full translation set…? Hmm.

  • Luke Stark, about 2 hours later:

    Funny thing, just yesterday my boss was asking about how easy it will be to send out strings for translation in our app. We’ll fiddle and see how it works alongside Globalize.

    Thanks. :)

  • Ben Kittrell, about 3 hours later:

    Freaking awesome. It’s always great when one of Rails’ “weaknesses” is conquered with one of the coolest implementations of all.

    Rats of to ya.

  • DEkart, about 3 hours later:

    Very useful thing. I’ve tried to use Globalize, but your plugin looks more simple and convenient for my needs. Thanks a lot :)

  • Anders Engström, about 3 hours later:

    Everyone is writing their own i18n library it seems :) I’m not entirely sure that is a bad thing, though. Everyone seem to have different requirements (depending on app, nationality etc.).

    I’ve implemented something that looks similar to Gibberish, but the configuration is done in plain ruby code, and the ‘localization context’ is thread-local:

    
    # Define stuff
    Localization.in_context("sv") do |l|
      l.instance_eval do
        define :name, "Namn" 
        define :greeting, "Hello, %s" 
        define :time, proc{|*args| (t.first || Time.now).strftime("%H:%M")}
      end
    end
    
    # To use..
    Localization.in_context("sv") do
      puts _(:name) #=> "Namn" 
      puts _(:greeting, "Anders") #=> "Hello, Anders" 
      puts _(:time) #=> evaluated to formatted Time.now
      puts _(:time, @some_time_ref)
    end
    
  • Alex Deva, about 5 hours later:

    Typo now uses Anders’ library. I find it even easier to use than Gibberish, and it has support to autogenerate string resource files.

    Anders, I had to patch your library just a tiny bit, to help it support JavaScript localization too…

  • scoopr, about 6 hours later:

    How would caching work? could the htaccess stuff be tweaked to get /users/1/info.sv.html when a language cookie is set to sv ? or just have prefix /sv/users/1/info.html .. would make invalidating a bit hard.

  • Greg Spurrier, about 6 hours later:

    Very cool. I’ll be needing something like this soon, so I’ll keep my eye on it.

    One question: if the string interpolation is strictly based on the order of the arguments, what happens if the translated version uses the arguments in a different order than the English version?

  • Chris, about 21 hours later:

    Anders: Looks cool! I don’t think it’s a bad thing, either.

    scoopr: I haven’t hit this yet. PDI?

    Greg: Great question. Try this changeset which opens up interpolation via hash. If you’ve got a better idea please let me know.

  • Tim Blair, about 23 hours later:

    My first thought was “what if the interpolated variables are in a different order for different languages”. When I come to point it out, someone’s already mentioned it and it’s been fixed. Isn’t the Rails community great?

    Good work Chris, looks like an excellent job.

  • pascal, 1 day later:

    not exactly a gibberish problem… but how do you guys i18n error messages from validates_presence_of and friends ?

  • Saimon Moore, 1 day later:

    Hi Chris,

    From what you said about the reasons that drew you to creating Gibberish:

    "I also know keying my translations by a string is not fun.What if I want to change a comma? Or add an exclamation point!"

    I’d like to point out that using globalize this is not a problem at all.

    Keying by string is exactly the same as keying by symbol in the sense that both are keys.

    i.e. once you define a translatable string key, to add a comma or change the value in any way for the base language (I assume you mean for the base language) then all you need to do is modify/create the translation for the base language. You can have translations for the base language too.

    e.g. Locale.set(‘en’,’US’) “This is a translatable string”.t => This is a translatable string

    Change ‘translation’ of the key in ‘en’ locale

    Locale.set_translation(“This is a translatable string”, “This is a translatable string!”)

    “This is a translatable string”.t => This is a translatable string!

    There’s absolutely no need to change the key or create another key at all.

    Just wanted to point this out in case people thought this was a major drawback of globalize :)

    Regards,

    Saimon

  • Anders Engström, 1 day later:

    Pascal: I was hoping that Rails would resolve :message in validate_presence_of by simply calling #to_s on it. So – in my Localization lib I extend Object with:

      # Returns an object whos to_s will resolve the key in the current context. Used
      # to define a localized reference that will be resolved in runtime
      def __(key, *args)
        LateResolver.new(key, *args)
      end     
    

    The LateResolver is a proc that will resolve the message key to the “current” locale when to_s is called on the proc. That would (if my assumptions on how Rails handles stuff was true) allow me to do:

    validates_presence_of :customer_id, :message => __(:no_blank)
    

    Unfortunately, this is not how Rails works (not as far as I can tell anyway). If anyone with deeper knowledge about Rails want to correct me – please go ahead :)

  • Chris, 1 day later:

    Pascal: There exists ActiveRecord::Errors.default_error_messages, a hash of error message strings. Maybe Gibberish can override these with key’d equivalents at runtime? Would make it easier to localize them. Check validations.rb.

  • Fred Brunel, 8 days later:

    I’ve used GLoc (http://wiki.rubyonrails.org/rails/pages/GLoc) and it’s pretty much the same.

    What is the difference with your plugin? Does it use any specific Rails mechanic?

  • Gustavo Beathyate, 9 days later:

    Great! I know it has nothing to do with it but you would say “Bienvenido Amigo”, not “Recepcion Amigo”. Great work though.

  • amaia, 9 days later:

    just a comment about the translation example, i don’t know if in other parts of the spanish speaking world that translation would be ok but here in Spain “Welcome, friend!” would be “¡Bienvenido, amigo!” or “¡Bienvenida, amiga!” if it’s a female friend

    regards, amaia

  • amaia, 9 days later:

    oops, i didn’t see gustavo’s comment, it wasn’t there when i started to write ;)

  • Nick, 10 days later:

    I also use GLoc and it does seem pretty similar ;-)

  • Chris, 10 days later:

    All the localization libraries are pretty similar, yeah. The difference is in the API. GLoc, to my knowledge, doesn’t let you keep both the default string and the string’s translation key in your views. This is the main point of Gibberish.

    If you don’t care about putting your default strings in the view, then Gibberish probably isn’t for you.

    GLoc: l(:welcome_string_key)

    Gibberish: “Welcome”[:welcome]

    GLoc: l(:hello_string_key, name)

    Gibberish: “Hey, {name}”[:hello, name]

  • Jake, 15 days later:

    Maybe i missing something out by why should i use this plugin instead of gettext?

  • gaius, about 1 month later:

    I’m a big fan of the concept, and most of the implementation. This, however, gave me pause: <<< Like this:

    “Welcome, {user}”[:welcome_user, current_user.name] => “Welcome, Chris”

    The {user} bit will be replaced with current_user.name when being rendered. Works for translations, too. Naturally.

    Curly brace’d strings are interpolated in the order arguments are passed. The fact that it says user is irrelevant. Really, it’s only to make things easy to remember. The important part is that it’s the first interpolation bullseye in the string. >>>

    What if the language I’m translating to has a different sentence order? In Chinese, Time often comes before Subject, whereas that order is flexible in English. And I don’t want to have to pick the order I pass the arguments based on what language I’m translating to; that would defeat the whole thing!

    Unless, of course, the translations have an ordering in them, like Java’s I18N: welcome_user: “Hello, {0}. The time is now {1}.”

    I sure hope you mean “the interpolation bullseye with the lowest index in the string.”

  • Chris, about 1 month later:

    gaius: See comments above, this has been addressed here.

  • Kathy, about 1 month later:

    Whenever I try to download from the svn://errtheblog.com/svn/plugins/gibberish subversion account it asks for a username = ? and password = ?. Could someone email those to me? Thanks, Kathy KathysKode@gmail.com

  • Deni, 3 months later:

    Great plugin – simple and very easy to use.

    Btw, there’s a small typo in the post: I think “RAILS_ROOT + ’/langs’” should be “RAILS_ROOT + ’/lang’”.

    Regards, Deni

  • Jamal, 6 months later:

    You will get error when you add empty language yml files :)

    You need to fill them up to not get this error below…

    $ ruby script/console Loading development environment (Rails 1.2.5) /Users/account/Documents/RubyonRailsApps/languages/vendor/plugins/gibberish/lib/gibberish/localize.rb:56:in `load_languages!’:NoMethodError: undefined method `symbolize_keys’ for false:FalseClass

    PS: Just in case

  • Fernando, 6 months later:

    Can this translate data from database?, I used a cookbook “tutorial” and did:

    <% Gibberish.current_language =:es %>

    <% for recipe in @recipes %> <% title = recipe.title[] %> <%= link_to %Q{#{title}}, ...

    But only some recipes titles are translated even though I have all of them in my es.yml. What confuses me the most is that if I use those same titles as strings in my page the translation works, but not when I read them from database.

    I’m sorry to bother you, I’m sure it must be something very simple that I’m not seeing.

    Thanks in advance!

  • Nikolay Petrov, 6 months later:

    Hi,

    I wandered for a little time and then added a non invasive snipped to reload translations on the fly if the mode of the rails is development. Here it is: if ENV[‘RAILS_ENV’] == ‘development’ puts “Development Mode” end

    language_paths = [RAILS_ROOT]
    paths = language_paths.map {|path| Dir[File.join(path, 'lang', '*.{yml,yaml}')]}.flatten
    rfiles = paths.map {|path| File.new(path)}
    Thread.new(rfiles) do |files|
      puts "Lang reload - started" 
      start_times = files.map {|file| file.mtime }
      while(true)
        sleep 1
        times = files.map {|file| file.mtime }
        next if start_times == times
        puts "Lang reload - reaload" 
        Gibberish.load_languages!
        start_times = times
      end
    end
  • Nikolay Petrov, 6 months later:

    Oh no the formatting:

    if ENV[‘RAILS_ENV’] == ‘development’ puts “Development Mode” language_paths = [RAILS_ROOT] paths = language_paths.map {|path| Dir[File.join(path, ‘lang’, ’*.{yml,yaml}’)]}.flatten rfiles = paths.map {|path| File.new(path)} Thread.new(rfiles) do |files| puts “Lang reload – started” start_times = files.map {|file| file.mtime } while(true) sleep 1 times = files.map {|file| file.mtime } next if start_times == times puts “Lang reload – reaload” Gibberish.load_languages! start_times = times end end end

  • Catata, 8 months later:

    Yidagoo gadaguys adagar adall nadagerds!!!!

  • vjt, 8 months later:

    Active Record validation errors + Gibberish = love -> explains all :).

  • vjt, 8 months later:

    ehm, sorry, the link is not an image ..

  • Chris Eppstein, 8 months later:
    I’ve written an extension to gibberish for my team at http://www.caring.com that provides the following support:
    • storage of strings in the database
    • output of string to html in a way that allows us to know which string is actually being displayed (wraps it in a span that sets the class and lang) when passed through h() in an rhtml file.

    On top of this, we’ve written controllers and some javascript to allow editing-in-place of strings while you’re interacting with the site. It’s very nice – we’re using it to manage our site-copy.

    Checkout the code here: http://www.eppsteins.net/rails-plugins/gibberish_db

    Read the docs here: http://www.eppsteins.net/rails-plugins/gibberish_db/rdoc/index.html

    Hope you find this helpful.

  • face, 8 months later:

    I tried overriding ActiveRecord::Errors.default_error_messages for a site that changes locale based on the user’s preference (HTTP headers or RESTful routes). Unfortunately Rails validations cache strings at object load time, which happens long before the around filter.

    So I made a simple plugin gibberish_rails that overrides some core Rails validation methods. Note: This plugin is in a prototype state and very Rails 2.0.2 specific. However, I think it makes a great example to anyone facing this same problem. I plan to rewrite this plugin and simplify it once Rail’s issue 9726 is fixed.

    Thanks for creating the wonderful Gibberish plugin!

  • Branko Vukelic, 9 months later:

    Are there any plans for Rake tasks to extract all gibberish strings appearing anywhere in the code into a YML file?

  • Tim, 9 months later:

    I can’t download from svn://errtheblog.com/svn/plugins/gibberish/. Is it possible the site is down?

  • Fred, 9 months later:

    Anyone using this plugin with a rails project that is also using Hpricot? After installing Gibberish it seems that perhaps the StringExt is causing collisions with method []

    NoMethodError: undefined method `filter[:]’ for #

  • dani, 10 months later:

    bienvenido is welcome in spanish. great blog. thankyou for share with us!

  • Tom, 10 months later:

    why does this not work?

    class Emailer < ActionMailer::Base

    @body[:sender_name] = "Sent By, #{sender_name}" [:sent_by, sender_name]
    @body[:sender_email] = "Email, #{sender_email}"[:user_email, sender_email]

    end

    It translates the sent by/Email string fine but it doesn’t add in the user specific info????

  • Matt Powell, 11 months later:

    Here’s a little something I’ve added into my application_helper.rb to make select boxes for picking languages easier. Just stick a language_name: French key in your fr.yaml file.

      def language_options
        @language_options ||= returning [] do |languages|
          ([ :en ] + Gibberish.languages).each do |lang|
            Gibberish.use_language(lang) do
              languages << [ lang.to_s[:language_name], lang ]
            end
          end
        end
      end
    
  • Jaryl Sim, 11 months later:

    I’d believe that you’d have to do this instead:

    @body[:sender_name] = “Sent By, {#{sender_name}}” [:sent_by, sender_name] @body[:sender_email] = “Email, {#{sender_email}}” [:user_email, sender_email]

  • Jamie Conlon, about 1 year later:

    Gibberish is great =)

    However, there does appear to be a conflict with it and Hpricot. If an element in Hpricot contains a colon, such as you would find if you try to parse youtube’s api:

    @doc.at(“yt:duration”)

    it tosses up an error:

    NoMethodError: undefined method `filter[:]’ ...

    The problem comes up at line 306 in lib/hpricot/elements.rb, but I could not quickly see what was causing it..

  • SG, about 1 year later:

    Anyone here manage to get localized routes going?

    mysite.com/en/things/1

    mysite.com/es/cosas/1

    Ripping my hair out over here >:(

  • Igor, about 1 year later:

    Anyone have an idea when errtheblog.com will go up again?

  • werder, about 1 year later:

    Great post, the best article about this topic. funny jokes

  • Tomasz Mazur, about 1 year later:

    If you want to translate ActiveRecord messages with Gibberish (model, and fields names too) use this plugin: http://github.com/ncr/gibberish_trix/tree/master

  • karmi, about 1 year later:

    I remember there was some Rake task to extract texts from your source and dump them into Gibberish dictionary. I couldn’t find it, so I rolled this one: http://gist.github.com/4068/ . Please check it, enhance, link it.

    And thanks for Gibberish, it’s very, very smooth!

  • Heart Tattoos, about 1 year later:

    Tattoos Celtic Tattoos Lower Back Tattoos Dragon Tattoos Skull Tattoos Heart Tattoos Butterfly Tattoos Chinese Tattoos Layered Hair Styles Layered Hairstyles Emo Hairstyles Medium Hairstyles Bang Hairstyle Prom Hairstyle Hair Coloring Heart Lower Back Tattoos

  • sıcaklar, about 1 year later:

    sikiş porno sex video izle iyi porno uzun porno yeni pornolar porno seyret sex seyret porno filmler sex izleyin sex izle porno sex erotik porn video türk porno canlı porno porno izle porno porno film sex filmleri porn video porno film sex seyret porno video seyret orgazm porno seks izle erotik video sex videolar yetişkin video sex video izle porno video izle bedava porno 18 video seks porno sıcak izle yetişkin film sikiş seyret sex amatör videolar teen video erotik videolar yetişkin video yetişkin videolar pornolar porno video teen kızlık bozma sikiş sikiş video seks türban sex sex erotik seks izle sıcak ateşli

  • asd, about 1 year later:

    modern abstract art sofa manufacturer гранит 净水器 混合机 过滤机 DHL快递 保险箱 法兰 法兰标准 牛皮癣 皮肤病 北京快递公司 北京国际快递 传世私服 传奇世界私服 天龙八部私服 天龙私服 网络电话 免费网络电话 假发 补发 织发 植发 上海搬家公司 上海搬场公司 大众搬家 大众搬场 张家界旅游 香港旅游 深圳旅行社 打包机 收缩机 萎缩性胃炎 neoprene laptop bags SEO优化 SEO优化 计量泵 胃炎 胃病 冷水机 冰水机 工业冷水机 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 油罐车 北京办证 办证 北京特价机票 北京打折计票 北京国际机票 北京机票预定 北京飞机票 北京订机票 北京机票查询 血糖仪 血糖仪 银杏 水培花卉 企业宣传片 空分设备 机电设备安装 代孕 代孕网 代孕 代孕 代孕 试管婴儿 代孕 电话交换机 程控交换机 集团电话 集装袋 混合机混合机 混合机捏合机 捏合机 捏合机导热油炉 导热油炉 导热油炉 反应釜 反应釜 反应釜 回流焊 波峰焊 spherical roller bearing 搬运车 搬运车 电动搬运车 油桶搬运车 堆高车 电动堆高车 半电动堆高车 堆垛车 高空作业平台车 电动叉车 平衡重叉车 前移叉车 电瓶叉车 苗木价格 苗木信息 标牌制作 深圳标牌 儿童摄影 北京儿童摄影 防静电鞋 淘宝刷信誉 威海凤凰湖 威海海景房 大庆密封件 打标机 淘宝刷信誉 TESOL/TEFL国际英语教师证书 英语教师进修及培训 韩国饰品批发 代写论文 代写论文 代写论文 代写代发 论文代写 电源模块 模块电源 X架 超薄灯箱> 易拉宝 展柜制作 代理服务器 游戏加速器 网络加速器 网通加速器 电信加速器 电信网通转换器 电信网通加速器 网通电信互转 网通电信互通 网络游戏加速器 美国VPN代理 美国独享VPN 美国独享IP pvc ceiling panel Spherical roller bearings 天龙八部私服 SEO优化 安全鞋 劳保鞋 防砸鞋 电绝缘鞋 上海安全鞋 上海劳保鞋 江苏劳保鞋 服装软件 服装管理软件 进销存软件 进销存管理软件 服装管理系统 服装进销存软件 进销存系统 进销存管理系统 免费进销存软件 吉林中医 东北特产 打包机 dhl 阳痿 阴茎短小 阴茎增大 早泄 前列腺炎 阴茎增粗 阴茎延长 国际机票 上海国际机票 国际打折机票 国际特价机票 CRM 客户管理软件 客户关系管理 免费客户管理软件 客户管理软件下载 客户信息管理系统 销售管理系统 销售管理 CRM系统 CRM软件 客户关系管理系统 客户关系管理软件 客户管理 客户管理系统 营销管理系统 客户资源管理 销售管理软件 客户资料管理软件 客户资源管理软件 客户信息管理软件 客户资料管理 客户资源管理 客户信息管理 客户资料管理系统 客户资源管理系统 客户管理软件免费版 砂磨机 砂磨机 砂磨机 卧式砂磨机 卧式砂磨机 卧式砂磨机 三辊研磨机 三辊研磨机 三辊研磨机 混合机 混合机 混合机 锥形混合机 锥形混合机 锥形混合机 行星动力混合机 行星动力混合机 行星动力混合机 无重力混合机 无重力混合机 无重力混合机 干粉砂浆设备 干粉砂浆设备 干粉砂浆设备 捏合机 捏合机 捏合机 导热油炉 导热油炉 导热油炉 反应釜 反应釜 反应釜 搪玻璃反应釜 搪玻璃反应釜 搪玻璃反应釜 乳化机 涂料设备 干混砂浆设备 无重力混合机 胶体磨 涂料成套设备 双螺旋混合机 北京婚庆 北京婚庆公司 400电话 办证 呼吸机 制氧机 亚都 亚都加湿器 亚都净化器 亚都装修卫士 饰品批发 小饰品批发 韩国饰品 韩国饰品批发 premature ejaculation penis enlargement 破碎机 制砂机 球磨机 雷蒙磨 雷蒙磨粉机 鄂式破碎机 鄂式破碎机 免烧砖机 加气混凝土设备 反击式破碎机 选矿设备 安利产品 马来西亚留学 网站优化 网站推广 衬布 代写论文 代写论文 代写论文 论文代写 代写论文 代写硕士论文 代写毕业论文 磁力泵 离心泵 化工泵 隔膜泵 螺杆泵 潜水泵 油泵 耐腐蚀泵 泵 水泵 拖链 防护罩 排屑机 塑料拖链 钢铝拖链 水泵 磁力泵 隔膜泵 离心泵 液下泵 自吸泵 多级泵 排污泵 螺杆泵 油泵 化工泵 电动隔膜泵 气动隔膜泵 自吸式磁力泵 氟塑料磁力泵 管道离心泵 导热油泵 深井泵 潜水泵 污水泵 潜水排污泵 深圳装饰 深圳装饰公司 深圳装修公司 特价机票 打折机票 国际机票 机票 新风换气机 换气机 立式新风换气机 风机箱 新风系统 能量回收机 搅拌机 混合机 乳化机 分散机 毛刷 毛刷辊 工业毛刷 刷子 钢丝刷 涂层测厚仪 硬度计 兆欧表 激光测距仪 测振仪 转速表 温湿度计 风速仪 超声波测厚仪 粗糙度仪 噪音计 红外测温仪 万用表 硬度计 万用表 美容院 美容加盟 澳洲留学 澳大利亚留学 什么是法兰 电烤箱 酒店预定 北京酒店预定 北京酒店 离心机 nail equipment nail products nail product nail uv lamp nail uv lamp nail uv lamps uv nail lamp nail brush nail file nail tool nail tip nail gel curing uv lamps lights 万用表 风速仪 红外测温仪 噪音计

  • 123, about 1 year later:

    情趣用品,情趣用品,情趣用品,情趣用品,情趣用品,情趣,情趣,情趣,情趣,情人歡愉用品,情惑用品性哥,情人用品性哥,情趣用品,AIO交友愛情館,情人歡愉用品,美女視訊,情色交友,情人用品性哥,視訊交友,辣妹視訊,美女交友,性愛,嘟嘟成人網,按摩棒,震動按摩棒,微調按摩棒,情趣按摩棒,逼真按摩棒,G點,跳蛋,跳蛋,跳蛋,性感內衣,飛機杯,充氣娃娃,情趣娃娃,角色扮演,性感睡衣,後庭區,SM,潤滑液,情趣禮物,威而柔,香水,精油,芳香精油,自慰,自慰套,性感吊帶襪,情趣用品加盟,情人節禮物,情人節,吊帶襪,辣妹視訊,美女交友,情色交友,成人交友,視訊聊天室,美女視訊,視訊美女,情色視訊,免費視訊聊天,視訊交友,視訊聊天,AIO交友愛情館,嘟嘟成人網,成人貼圖,成人網站,AIO交友愛情館,情色,情色貼圖,情色文學,情色交友,色情聊天室,色情小說,七夕情人節,色情,A片,A片下載,免費A片,免費A片下載,情色視訊,情色電影,色情網站,辣妹視訊,視訊聊天室,情色視訊,免費視訊聊天,視訊聊天,美女視訊,視訊美女,美女交友,美女,情色交友,成人交友,自拍,本土自拍,情人視訊網,視訊交友90739,生日禮物,情色論壇,正妹牆,正妹,成人網站,A片,免費A片,A片下載,免費A片下載,AV女優,成人影片,色情A片,成人論壇,情趣,免費成人影片,成人電影,成人影城,愛情公寓,色情影片,保險套

  • qw, about 1 year later:

    Thanks so much for this! This is exactly what I was looking for

    mirc mırc mırç mirç mirc indir mirc yükle mirc yukle türkçe mirc mirc indir mirc islami sohbet kelebek kelebek script kelebek sohbet kelebek mirc chat çet cet çet odaları sohbet kanalları sohbet odaları kameralı sohbet kameralı chat sohbet eğlence mirc sohbet odaları sevgili arkadaş arkadaş bul arkaraş ara oto araba şarkı sözleri astroloji ikinci el telefon gazete gazeteler günlük gazeteler marifetname bedava domain ücretsiz domain benimurl parça kontör parça kontör radyo dinle bedava blog ücretsiz blog

  • noname, about 1 year later:

    video ödev indir şarkı sözleri video izle şiir türkü indir güzel sözler fıkra porno izle pornolar 18

  • , about 1 year later:

    Victorias Secret Victoria’s Secret Fashion show Victorias Secret Pink Victorias Secret Model Victorias Secret Credit Card Victorias Secret Coupon Code Victorias Secret Lingerie Victorias Secret Fashion Show 2005 Victorias Secret Fashion Show 2006 Victorias Secret Bra Victorias Secret Catalog Victorias Secret Pantie Victorias Secret Online Coupon Victorias Secret Fashion Show 2007 Victorias Secret Girl Free Shipping Victorias Secret Victorias Secret Home Victorias Secret Christmas Victoria’S Secret Pink Dog Victorias Secret Music Victorias Secret Semi Annual Sale Victorias Secret Jobs Victorias Secret Free Shipping Code Victorias Secret Shoes Victorias Secret Thong Victorias Secret Commercial Victorias Secret Promotional Code Victorias Secret Love Spell Victorias Secret Boots Victorias Secret Employment Victorias Secret Reviews Victorias Secret Jeans Victorias Secret Brasil Victorias Secret Bag

  • , about 1 year later:

    情人用品,情人用品性哥,情 人用品,情趣用品,視訊交友,視訊美女,視訊美女,視訊交友網,視訊聊天室,視訊聊天室,視訊 交友網,免費視訊聊天,辣妹視訊,辣妹視訊,情人視訊網

  • dd, about 1 year later:

    徵信社,案件討論,男女專區,法律諮詢,相關新聞,情趣用品,情趣用品,情趣精品,情趣用品,情趣用品,情趣用品,情趣用品,威而柔,自慰套,自慰套,SM,充氣娃娃,充氣娃娃,潤滑液,飛機杯,按摩棒,跳蛋,性感睡衣

    威而柔,自慰套,自慰套,SM,充氣娃娃,充氣娃娃,潤滑液,飛機杯,按摩棒,跳蛋,性感睡衣,視訊交友90739,情人視訊網,情色交友,視訊交友,辣妹視訊,美女視訊,aio交友愛情館,情色論壇,成人論壇,免費視訊聊天,辣妹視訊,視訊交友網,美女視訊,視訊交友,成人視訊,情趣用品,成人聊天室,情趣,情趣,視訊聊天室,視訊聊天,視訊聊天室,情色視訊,情人視訊網,免費視訊聊天室,aio交友愛情館,色情遊戲,寄情築園小遊戲,情色文學,一葉情貼圖片區

  • jj, about 1 year later:

    :-)))) Very interesting! Thanks!!! phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex phone sex mootzie cosmology edvard munch humorous quotations hundredth monkey brain teasers jillian ann shakespeare quotations bride of frankenstein gettysburg address bill of rights van gogh bowling tips violin books eden prosper julia dreyfus violin bows chess download xslt aviation funny quotes xslt tips gothic abs self hypnosis gothic clothes monique olivia noda amanda roberts somethings happening bgreen68 bfire3 reldeve links psychology hypnosis phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex phonesex mootzie buffys bedroom blog the great adventure