From: gc Date: Sat, 1 Mar 2008 00:08:46 +0000 (+0000) Subject: multi languages, in backend only for the moment X-Git-Tag: 0.9.0~101 X-Git-Url: http://git.zarb.org/?p=booh;a=commitdiff_plain;h=de3d4d21d41801e2b5d7cc809004dc49cadca104 multi languages, in backend only for the moment --- diff --git a/bin/booh b/bin/booh index e54a11f..d27fa97 100755 --- a/bin/booh +++ b/bin/booh @@ -3075,7 +3075,7 @@ def new_album theme_sizes = [] select_theme(theme_button.label, 'all', optimize432.active?, nil) $images_size.each { |s| - sizes.add(cb = Gtk::CheckButton.new(sizename(s['name']))) + sizes.add(cb = Gtk::CheckButton.new(sizename(s['name'], true))) if !s['optional'] cb.active = true end @@ -3283,7 +3283,7 @@ def properties select_theme(theme_button.label, 'all', optimize432.active?, nperrow) $images_size.each { |s| - sizes.add(cb = Gtk::CheckButton.new(sizename(s['name']))) + sizes.add(cb = Gtk::CheckButton.new(sizename(s['name'], true))) if limit_sizes if limit_sizes.include?(s['name']) cb.active = true diff --git a/bin/booh-backend b/bin/booh-backend index df3ad11..3effa7f 100755 --- a/bin/booh-backend +++ b/bin/booh-backend @@ -31,6 +31,8 @@ require 'booh/html-merges' #- bind text domain as soon as possible because some _() functions are called early to build data structures bindtextdomain("booh") +SUPPORTED_LANGUAGES = %w(en de fr ja eo) + #- options $options = [ [ '--help', '-h', GetoptLong::NO_ARGUMENT, _("Get help message") ], @@ -51,6 +53,7 @@ $options = [ [ '--force', '-f', GetoptLong::NO_ARGUMENT, _("Force generation of album even if the GUI marked some directories as already generated") ], [ '--sizes', '-S', GetoptLong::REQUIRED_ARGUMENT, _("Specify the list of images sizes to use instead of all specified in the theme (this is a comma-separated list)") ], + [ '--multi-languages', '-L', GetoptLong::REQUIRED_ARGUMENT, _("Specify the list of languages to support (uses Apache MultiViews); this is a comma-separated list of supported languages, with last element used as the default language; for example: 'fr,eo,en,en'; supported languages: %s") % SUPPORTED_LANGUAGES.join(', ') ], [ '--thumbnails-per-row', '-T', GetoptLong::REQUIRED_ARGUMENT, _("Specify the amount of thumbnails per row in the thumbnails page (if applicable in theme)") ], [ '--thumbnails-per-page', '-p', GetoptLong::REQUIRED_ARGUMENT, _("Specify the amount of thumbnails per page in the thumbnails page, after which split occurs") ], [ '--optimize-for-32', '-o', GetoptLong::NO_ARGUMENT, _("Resize images with optimized sizes for 3/2 aspect ratio rather than 4/3 (typical aspect ratio of pictures from non digital cameras are 3/2 when pictures from digital cameras are 4/3)") ], @@ -193,6 +196,13 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % when '--sizes' $limit_sizes = arg + when '--multi-languages' + parts = arg.split(',') + if parts.size == 0 || parts.find_all { |e| ! SUPPORTED_LANGUAGES.include?(e.strip) }.size > 0 + die _("--multi-languages: argument must be a comma-separated list of supported languages, with last element used as the default language; for example: 'fr,eo,en,en'; supported languages: %s") % SUPPORTED_LANGUAGES.join(', ') + end + $multi_languages = [ parts[0..-2], parts[-1] ] + when '--thumbnails-per-row' $N_per_row = arg @@ -243,6 +253,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % if $mode == 'use_config' || $mode =~ /^merge_config/ $optimize_for_32 = !$xmldoc.root.attributes['optimize-for-32'].nil? $N_per_row = $xmldoc.root.attributes['thumbnails-per-row'] + languages = $xmldoc.root.attributes['multi-languages'] + if languages + languages = languages.split(',') + $multi_languages = [ languages[0..-2], languages[-1] ] + end $N_per_page = $xmldoc.root.attributes['thumbnails-per-page'] $madewith = $xmldoc.root.attributes['made-with'] $indexlink = $xmldoc.root.attributes['index-link'] @@ -274,6 +289,9 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % if $limit_sizes additional_params += "limit-sizes='#{$limit_sizes}'" end + if $multi_languages + additional_params += " multi-languages='#{$multi_languages[0].join(',')},#{$multi_languages[1]}'" + end if $optimize_for_32 additional_params += " optimize-for-32='true'" end @@ -302,6 +320,12 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % else $xmldoc.root.delete_attribute('limit-sizes') end + if $multi_languages + $xmldoc.root.add_attribute('multi-languages', $multi_languages[0].join(',') + ',' + $multi_languages[1]) + else + $xmldoc.root.delete_attribute('multi-languages') + end + if $optimize_for_32 $xmldoc.root.add_attribute('optimize-for-32', 'true') else @@ -332,6 +356,11 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") % if $madewith $madewith = $madewith.gsub('%booh', '"http://booh.org/"') end + if $multi_languages + $htmlsuffix = '' + else + $htmlsuffix = '.html' + end end def read_config @@ -418,11 +447,12 @@ def html_reload_to_thumbnails html_reload_to_thumbnails = $preferred_size_reloader.clone html_reload_to_thumbnails.gsub!(/~~theme~~/, $theme) html_reload_to_thumbnails.gsub!(/~~default_size~~/, $default_size['name']) + html_reload_to_thumbnails.gsub!(/~~htmlsuffix~~/, $htmlsuffix) html_reload_to_thumbnails.gsub!(/~~all_sizes~~/, all_images_sizes.collect { |s| "\"#{size2js(s['name'])}\"" }.join(', ')) size_auto_chooser = ''; all_images_sizes.find_all { |s| s.has_key?('optimizedforwidth') }. sort { |a,b| b['optimizedforwidth'].to_i <=> a['optimizedforwidth'].to_i }. - each { |s| size_auto_chooser += "if (w + 50 > #{s['optimizedforwidth']}) { return 'thumbnails-#{size2js(s['name'])}-0.html'; }\n" } + each { |s| size_auto_chooser += "if (w + 50 > #{s['optimizedforwidth']}) { return 'thumbnails-#{size2js(s['name'])}-0#{$htmlsuffix}'; }\n" } html_reload_to_thumbnails.gsub!(/~~size_auto_chooser~~/, size_auto_chooser) return html_reload_to_thumbnails end @@ -519,10 +549,10 @@ def substitute_html_sizes(html, sizeobj, type, suffix) if $images_size.length > 1 || (type == 'image' && $limit_sizes =~ /original/) for sizeobj2 in $images_size sizejs = size2js(sizeobj2['name']) - sizen = sizename(sizeobj2['name']) + sizen = defer_translation(sizename(sizeobj2['name'], false)) if sizeobj != sizeobj2 if type == 'thumbnails' - sizestrings << '' + sizen + '' + sizestrings << '' + sizen + '' else sizestrings << '' + sizen + '' end @@ -531,7 +561,7 @@ def substitute_html_sizes(html, sizeobj, type, suffix) end end if type == 'image' && $limit_sizes =~ /original/ - sizestrings << '' + sizename('original') + '' + sizestrings << '' + defer_translation(sizename('original'), false) + '' end end html.sub!(/~~sizes~~(.+)~~/) { sizestrings.join($1) } @@ -544,7 +574,7 @@ def substitute_navigation(html, xmldir) parent = xmldir.parent while parent.name == 'dir' parentcaption = parent.attributes['subdirs-caption'] || File.basename(parent.attributes['path']) - nav = "#{parentcaption} #{utf8(_(" > "))} #{nav}" + nav = "#{parentcaption} #{defer_translation(N_(" > "))} #{nav}" path += '/..' parent = parent.parent end @@ -626,16 +656,29 @@ def find_next_album(xmldir) return File.reduce_path(relative_pos) end -def sub_previous_next_album(previous_album, next_album, html) +def find_translation_for_file(file, msg) + if $multi_languages + if file =~ /\.(\w\w)\.html$/ + bindtextdomain("booh", { :locale => "#{$1}.UTF-8" }) + return _(msg) + else + die "Internal error: cannot find multi language suffix of file '#{file}'" + end + else + return utf8(_(msg)) + end +end + +def sub_previous_next_album(file, previous_album, next_album, html) if previous_album - html.gsub!(/~~previous_album~~/, '' + utf8(_('previous album')) + '') + html.gsub!(/~~previous_album~~/, '' + find_translation_for_file(file, N_('previous album')) + '') html.gsub!(/~~ifprevious_album\?~~(.+?)~~fi~~/) { $1 } else html.gsub!(/~~previous_album~~/, '') html.gsub!(/~~ifprevious_album\?~~(.+?)~~fi~~/, '') end if next_album - html.gsub!(/~~next_album~~/, '' + utf8(_('next album')) + '') + html.gsub!(/~~next_album~~/, '' + find_translation_for_file(file, N_('next album')) + '') html.gsub!(/~~ifnext_album\?~~(.+?)~~fi~~/) { $1 } else html.gsub!(/~~next_album~~/, '') @@ -644,6 +687,24 @@ def sub_previous_next_album(previous_album, next_album, html) return html end +def save_html(html, base_filename) + if html.class == Array + html = html.join("\n") + end + if $multi_languages + for language in $multi_languages[0] + bindtextdomain("booh", { :locale => "#{language}.UTF-8" }) + ios = File.open("#{base_filename}.#{language}.html", "w") + ios.write(html.gsub(/@@(.*?)@@/) { _($1) }) + ios.close + end + else + ios = File.open("#{base_filename}.html", "w") + ios.write(html.gsub(/@@(.*?)@@/) { utf8(_($1)) }) + ios.close + end +end + def walk_source_dir #- preprocess the path->dir, rexml is very slow with that; we seem to improve speed by 7% @@ -782,6 +843,11 @@ def walk_source_dir msg 3, _("\tgenerating password protection file #{dest_dir}/.htaccess") ios.write("AuthType Basic\nAuthName \"protected area\"\nAuthUserFile #{auth_user_file}\nrequire valid-user\n") end + if $multi_languages + ios.write("LanguagePriority #{$multi_languages[1]}\n") + ios.write("ForceLanguagePriority Prefer Fallback\n") + ios.write("DirectoryIndex index\n") + end ios.close end @@ -1015,7 +1081,7 @@ def walk_source_dir '' + img_element("#{dest_dir}/#{thumbnail_videos[sizeobj['name']][index]}") + '') else html_elem.gsub!(/~~image_iteration~~/, - '' + utf8(_("(no preview)")) + '') + '' + defer_translation(N_("(no preview)")) + '') end html_elem.gsub!(/~~caption_iteration~~/, find_caption_value(xmldir, videos[index]) || utf8(videos[index])) html_elem.gsub!(/~~ifimage\?~~(.+?)~~fi~~/, '') @@ -1025,7 +1091,7 @@ def walk_source_dir html_thumbnails_nojs += html_elem if type == 'image' html_thumbnails.gsub!(/~~image_iteration~~/, - '' + img_element("#{dest_dir}/#{thumbnail_images[sizeobj['name']][index]}") + '') html_thumbnails_nojs.gsub!(/~~image_iteration~~/, @@ -1057,6 +1123,7 @@ def walk_source_dir for i in html i.gsub!(/~~theme~~/, $theme) i.gsub!(/~~current_size~~/, sizeobj['name']) + i.gsub!(/~~htmlsuffix~~/, $htmlsuffix) i.gsub!(/~~current_size_js~~/, size2js(sizeobj['name'])) i.gsub!(/~~madewith~~/, $madewith || '') i.gsub!(/~~indexlink~~/, $indexlink || '') @@ -1067,12 +1134,13 @@ def walk_source_dir for page in all_pages html_thumbnails, html_thumbnails_nojs = page final_html = html.collect { |l| l.clone } - mstuff = utf8(_("Pages: %s") % (pagecount > 0 ? "" + _("<- Previous") + " " : '') + - all_pages.collect_with_index { |p,idx| page == p ? idx + 1 : "#{idx + 1}" }.join(', ') + - (pagecount < all_pages.size - 1 ? " " + _("Next ->") + " " : '')) + mstuff = defer_translation(N_("Pages: ")) + + (pagecount > 0 ? "" + defer_translation(N_("<- Previous")) + " " : '') + + all_pages.collect_with_index { |p,idx| page == p ? idx + 1 : "#{idx + 1}" }.join(', ') + + (pagecount < all_pages.size - 1 ? " " + defer_translation(N_("Next ->")) + " " : '') for i in final_html i.sub!(/~~run_slideshow~~/, - images.size <= 1 ? '' : '' + utf8(_("Run slideshow!"))+'') + images.size <= 1 ? '' : '' + defer_translation(N_("Run slideshow!"))+'') i.sub!(/~~thumbnails~~/, html_thumbnails) if all_pages.size == 1 i.gsub!(/~~ifmultiplepages\?~~.*~~fi~~/, '') @@ -1083,12 +1151,10 @@ def walk_source_dir substitute_html_sizes(i, sizeobj, 'thumbnails', "-#{pagecount}") substitute_pathtobase(i, xmldir) end - ios = File.open("#{dest_dir}/thumbnails-#{size2js(sizeobj['name'])}-#{pagecount}.html", "w") - ios.write(final_html) - ios.close + save_html(final_html, "#{dest_dir}/thumbnails-#{size2js(sizeobj['name'])}-#{pagecount}") final_html_nojs = html_nojs.collect { |l| l.clone } for i in final_html_nojs - i.sub!(/~~run_slideshow~~/, utf8(_("Click on an image to view it larger"))) + i.sub!(/~~run_slideshow~~/, defer_translation(N_("Click on an image to view it larger"))) i.sub!(/~~thumbnails~~/, html_thumbnails_nojs) if all_pages.size == 1 i.gsub!(/~~ifmultiplepages\?~~.*~~fi~~/, '') @@ -1098,9 +1164,7 @@ def walk_source_dir end substitute_html_sizes(i, sizeobj, 'thumbnails', "-nojs-#{pagecount}") end - ios = File.open("#{dest_dir}/thumbnails-#{size2js(sizeobj['name'])}-nojs-#{pagecount}.html", "w") - ios.write(final_html_nojs) - ios.close + save_html(final_html_nojs, "#{dest_dir}/thumbnails-#{size2js(sizeobj['name'])}-nojs-#{pagecount}") pagecount += 1 end end @@ -1108,9 +1172,7 @@ def walk_source_dir info("finished processing sizes") #- generate "main" thumbnails.html page that will reload to correct size thanks to cookie - ios = File.open("#{dest_dir}/thumbnails.html", "w") - ios.write(html_reload_to_thumbnails) - ios.close + save_html(html_reload_to_thumbnails, "#{dest_dir}/thumbnails") #- generate image.html (page with fullscreen images) if images.size > 0 @@ -1134,18 +1196,17 @@ def walk_source_dir i.gsub!(/~~other_sizes~~/, othersizes.join(', ')) i.gsub!(/~~captions~~/, captions4js) i.gsub!(/~~title~~/, xmldir.attributes['thumbnails-caption'] || utf8(File.basename(dir))) - i.gsub!(/~~thumbnails~~/, '' + utf8(_('return to thumbnails')) + '') + i.gsub!(/~~thumbnails~~/, '' + defer_translation(N_('return to thumbnails')) + '') i.gsub!(/~~theme~~/, $theme) i.gsub!(/~~current_size~~/, size2js(sizeobj['name'])) + i.gsub!(/~~htmlsuffix~~/, $htmlsuffix) i.gsub!(/~~madewith~~/, $madewith || '') i.gsub!(/~~indexlink~~/, $indexlink || '') substitute_html_sizes(i, sizeobj, 'image', '') substitute_navigation(i, xmldir) substitute_pathtobase(i, xmldir) end - ios = File.open("#{dest_dir}/image-#{size2js(sizeobj['name'])}.html", "w") - ios.write(html) - ios.close + save_html(html, "#{dest_dir}/image-#{size2js(sizeobj['name'])}") end end end @@ -1239,7 +1300,7 @@ def walk_source_dir gen_thumbnails_subdir(from_utf8(xmldir.attributes['thumbnails-captionfile']), xmldir, false, [ { 'filename' => thumbnail, 'size' => $albums_thumbnail_size } ], 'thumbnails') html_index += run_iterations(iterations, 1) - html_index.gsub!(/~~image_iteration~~/, "" + img_element(thumbnail) + '') + html_index.gsub!(/~~image_iteration~~/, "" + img_element(thumbnail) + '') html_index.gsub!(/~~caption_iteration~~/, xmldir.attributes['thumbnails-caption']) end @@ -1255,7 +1316,7 @@ def walk_source_dir gen_thumbnails_subdir(captionfile, child, false, [ { 'filename' => thumbnail, 'size' => $albums_thumbnail_size } ], find_subalbum_info_type(child)) html_index.gsub!(/~~caption_iteration~~/, caption) - html_index.gsub!(/~~image_iteration~~/, "" + img_element(thumbnail) + '') + html_index.gsub!(/~~image_iteration~~/, "" + img_element(thumbnail) + '') } html_index += close_iterations(iterations) @@ -1270,9 +1331,13 @@ def walk_source_dir html = html_reload_to_thumbnails end - ios = File.open("#{dest_dir}/index.html", "w") - ios.write(html) - ios.close + save_html(html, "#{dest_dir}/index") + if $multi_languages + #- in case MultiViews will not work, generate some compat + ios = File.open("#{dest_dir}/index.html", "w") + ios.write("") + ios.close + end #- substitute multiple "return to albums", previous/next correctly #- the following two statements are dramatical optimizations to executing for each substInFile callback @@ -1283,21 +1348,23 @@ def walk_source_dir for sizeobj in $images_size Dir.glob("#{dest_dir}/thumbnails-#{size2js(sizeobj['name'])}#{suffix}-*.html") do |file| substInFile(file) { |line| - sub_previous_next_album(previous_album, next_album, line) + sub_previous_next_album(file, previous_album, next_album, line) if dirpresent - line.sub!(/~~return_to_albums~~/, '' + utf8(_('return to albums')) + '') + line.sub!(/~~return_to_albums~~/, '' + find_translation_for_file(file, N_('return to albums')) + '') else if parentname == 'dir' - line.sub!(/~~return_to_albums~~/, '' + utf8(_('return to albums')) + '') + line.sub!(/~~return_to_albums~~/, '' + find_translation_for_file(file, N_('return to albums')) + '') else line.sub!(/~~return_to_albums~~/, '') end end line } - if suffix == '' && xmldir.child_byname_notattr('image', 'deleted') - substInFile("#{dest_dir}/image-#{size2js(sizeobj['name'])}.html") { |line| - sub_previous_next_album(previous_album, next_album, line) + end + if suffix == '' && xmldir.child_byname_notattr('image', 'deleted') + Dir.glob("#{dest_dir}/image-#{size2js(sizeobj['name'])}*.html") do |file| + substInFile(file) { |line| + sub_previous_next_album(file, previous_album, next_album, line) } end end diff --git a/data/booh/themes/simple/root/booh.js b/data/booh/themes/simple/root/booh.js index 3268972..c9fdef6 100644 --- a/data/booh/themes/simple/root/booh.js +++ b/data/booh/themes/simple/root/booh.js @@ -223,10 +223,10 @@ function show_current_text() { if (other_sizes[i] == "original") { document.getElementById('link' + other_sizes[i]).href = eval("images_" + other_sizes[i] + "[current]"); } else { - document.getElementById('link' + other_sizes[i]).href = 'image-' + other_sizes[i] + '.html#current=' + eval("images_" + other_sizes[i] + "[current]"); + document.getElementById('link' + other_sizes[i]).href = 'image-' + other_sizes[i] + dbltilda_htmlsuffix + '#current=' + eval("images_" + other_sizes[i] + "[current]"); } } - document.getElementById('thumbnails').href = 'thumbnails-' + dbltilda_current_size + '-' + thumbnailspages[current] + '.html#' + images[current]; + document.getElementById('thumbnails').href = 'thumbnails-' + dbltilda_current_size + '-' + thumbnailspages[current] + dbltilda_htmlsuffix + '#' + images[current]; set_cursor("default"); } else { setTimeout("show_current_text()", 50); @@ -237,7 +237,7 @@ function show_current_text() { function display_current() { document.main_img.src = images[current]; oldhref = browser_href(); - newhref = 'image-' + dbltilda_current_size + '.html#current=' + images[current]; + newhref = 'image-' + dbltilda_current_size + dbltilda_htmlsuffix + '#current=' + images[current]; if (oldhref != newhref) { currentURL = 'ignore1'; location.href = newhref; diff --git a/lib/booh/booh-lib.rb b/lib/booh/booh-lib.rb index e593cb3..804add3 100644 --- a/lib/booh/booh-lib.rb +++ b/lib/booh/booh-lib.rb @@ -58,12 +58,17 @@ module Booh end end - def sizename(key) + def sizename(key, translate) #- fake for gettext to find these; if themes need more sizes, english name for them should be added here - sizenames = { 'small' => utf8(_("small")), 'medium' => utf8(_("medium")), 'large' => utf8(_("large")), - 'x-large' => utf8(_("x-large")), 'xx-large' => utf8(_("xx-large")), - 'original' => utf8(_("original")) } - return sizenames[key] || key + sizenames = { 'small' => N_("small"), 'medium' => N_("medium"), 'large' => N_("large"), + 'x-large' => N_("x-large"), 'xx-large' => N_("xx-large"), + 'original' => N_("original") } + sizename = sizenames[key] || key + if translate + return utf8(_(sizename)) + else + return sizename + end end def from_utf8(string) @@ -824,6 +829,9 @@ French: Guillaume Cottenceau')), return sorted_entries end + def defer_translation(msg) + return "@@#{msg}@@" + end end class File diff --git a/lib/booh/html-merges.rb b/lib/booh/html-merges.rb index ee89dd8..e04e2a4 100644 --- a/lib/booh/html-merges.rb +++ b/lib/booh/html-merges.rb @@ -41,11 +41,12 @@ dbltilda_current_size = '~~current_size~~'; dbltilda_theme = '~~theme~~'; dbltilda_stop_slideshow = '~~stop_slideshow~~'; dbltilda_run_slideshow = '~~run_slideshow~~'; +dbltilda_htmlsuffix = '~~htmlsuffix~~'; EOF -$image_head_code.sub!('~~run_slideshow~~', utf8(_('Run slideshow!'))) -$image_head_code.sub!('~~stop_slideshow~~', utf8(_('Stop slideshow'))) +$image_head_code.sub!('~~run_slideshow~~', defer_translation(N_('Run slideshow!'))) +$image_head_code.sub!('~~stop_slideshow~~', defer_translation(N_('Stop slideshow'))) $body_additions = <<'EOF' onload="init()" id="body" @@ -54,35 +55,35 @@ EOF $button_first = '
' $button_previous = '
' $button_next = '
' $button_last = '
' $button_slideshow = ' ' $pause_slideshow = ' - ' + utf8(_('pause:')) + '' + utf8(_('secs')) + '' + ' + defer_translation(N_('pause:')) + '' + defer_translation(N_('secs')) + '' $image = <<'EOF' @@ -136,21 +137,21 @@ function getPreferredSize() { size = document.cookie.substring(oleft, oright); for (i = 0; i < sizes.length; i++) { if (sizes[i] == size) { - return 'thumbnails-' + size + '-0.html'; + return 'thumbnails-' + size + '-0~~htmlsuffix~~'; } } } } w = document.body.offsetWidth; ~~size_auto_chooser~~ - return 'thumbnails-~~default_size~~-0.html'; + return 'thumbnails-~~default_size~~-0~~htmlsuffix~~'; } window.location.href = getPreferredSize(); - + EOF @@ -159,7 +160,7 @@ $index_head_code = ' function init() { if (!document.cookie || document.cookie.indexOf("booh-not-a-newbie") == -1) { - document.getElementById("title").innerHTML += "

' + utf8(_("Hint: you can click on the images to open the albums!")) + '"; + document.getElementById("title").innerHTML += "

' + defer_translation(N_("Hint: you can click on the images to open the albums!")) + '"; } var expires = new Date(new Date().getTime() + (10 * 86400000)); // 10 days document.cookie = "booh-not-a-newbie=true"