fixup! fixup! [#8182] Improvements to Category/Trove admin
diff --git a/Allura/allura/controllers/trovecategories.py b/Allura/allura/controllers/trovecategories.py
index be8e7ea..2e2c33f 100644
--- a/Allura/allura/controllers/trovecategories.py
+++ b/Allura/allura/controllers/trovecategories.py
@@ -144,9 +144,9 @@
             else:
                 flash('An error occured while crearing the category.', "error")
         if upper:
-            redirect('/categories/{}/?categoryname={}&shortname={}'.format(upper.trove_cat_id, name, shortname))
+            redirect(u'/categories/{}/?categoryname={}&shortname={}'.format(upper.trove_cat_id, name, shortname))
         else:
-            redirect('/categories/?categoryname={}&shortname={}'.format(name, shortname))
+            redirect(u'/categories/?categoryname={}&shortname={}'.format(name, shortname))
 
     @expose()
     @require_post()
diff --git a/Allura/allura/ext/admin/templates/project_trove.html b/Allura/allura/ext/admin/templates/project_trove.html
index 81173cf..ea1a3bf 100644
--- a/Allura/allura/ext/admin/templates/project_trove.html
+++ b/Allura/allura/ext/admin/templates/project_trove.html
@@ -94,7 +94,7 @@
       </form>
     </div>
   </div>
-  {% for base in base_troves %}
+  {% for base in base_troves if hasattr(c.project, "trove_{}".format(base.shortname))%}
     {{show_trove_base_cat(base)}}
   {% endfor %}
 {% endblock %}
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index 2be5139..572b6e6 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -1297,13 +1297,14 @@
     return 'data:{};base64,{}'.format(mimetype, data)
 
 
-def slugify(name):
+def slugify(name, allow_periods=False):
     """
-    Returns a tuple with slug and lowered slug ased on name, according to our specific rules for commercial software.
+    Returns a tuple with slug and lowered slug based on name
     """
+    dash_collapse_pattern = r'[^.\w]+' if allow_periods else r'[^\w]+'
     slug = re.sub(r'(^-)|(-$)', '',  # leading - or trailing - gets removed
                   unicode(
-                      re.sub(r'[^.\w]+', '-',  # replace non ". alphanum_" sequences into single -
+                      re.sub(dash_collapse_pattern, '-',  # replace non ". alphanum_" sequences into single -
                              re.sub(r"'", '',  # remove any apostrophes
                                     unicodedata.normalize('NFKD', name)
                                     .encode('ascii', 'ignore')))
diff --git a/Allura/allura/lib/widgets/forms.py b/Allura/allura/lib/widgets/forms.py
index 871d809..d92471c 100644
--- a/Allura/allura/lib/widgets/forms.py
+++ b/Allura/allura/lib/widgets/forms.py
@@ -599,12 +599,12 @@
                 show_errors=False,
                 show_label=False,
                 fields=[
-                    ew.HTMLField(
-                        text=cat.shortname,
-                        attrs={'disabled':True, 'value':cat.shortname}),
                     ew.LinkField(
                         text=cat.fullname,
                         href="/categories/%s" % cat.trove_cat_id),
+                    ew.HTMLField(
+                        text=cat.shortname,
+                        attrs={'disabled':True, 'value':cat.shortname}),
                     ew.SubmitButton(
                         show_errors=False,
                         attrs={'value': 'Remove'})],
@@ -643,8 +643,6 @@
         upper_category = kw.get('uppercategory_id', 0)
 
         self.fields['uppercategory_id'].attrs['value'] = upper_category
-        # self.fields['shortname'].attrs['value'] = kw.get('shortname', '')
-        # self.fields['categoryname'].attrs['value'] = kw.get('categoryname', '')
         return super(ForgeForm, self).display(**kw)
 
     @ew_core.core.validator
diff --git a/Allura/allura/templates/trovecategories.html b/Allura/allura/templates/trovecategories.html
index 0e82aab..ff7959c 100644
--- a/Allura/allura/templates/trovecategories.html
+++ b/Allura/allura/templates/trovecategories.html
@@ -47,8 +47,8 @@
       <table>
         <thead>
           <tr>
-            <th>Short Name</th>
             <th>Name</th>
+            <th>Short Name</th>
             <th>Actions</th>
           </tr>
         </thead>
diff --git a/Allura/allura/tests/test_helpers.py b/Allura/allura/tests/test_helpers.py
index fbc9813..e7ace1c 100644
--- a/Allura/allura/tests/test_helpers.py
+++ b/Allura/allura/tests/test_helpers.py
@@ -601,3 +601,15 @@
 def test_base64uri_text():
     b64txt = h.base64uri('blah blah blah 123 456 foo bar baz', mimetype='text/plain')
     assert b64txt.startswith('data:text/plain;base64,'), b64txt
+
+
+def test_slugify():
+    assert_equals(h.slugify(u'Foo Bar Bat')[0], 'Foo-Bar-Bat')
+    assert_equals(h.slugify(u'Foo_Bar')[0], 'Foo_Bar')
+    assert_equals(h.slugify(u'Foo   ')[0], 'Foo')
+    assert_equals(h.slugify(u'    Foo   ')[0], 'Foo')
+    assert_equals(h.slugify(u'"    Foo   ')[0], 'Foo')
+    assert_equals(h.slugify(u'Fôö')[0], 'Foo')
+    assert_equals(h.slugify(u'Foo.Bar')[0], 'Foo-Bar')
+    assert_equals(h.slugify(u'Foo.Bar', True)[0], 'Foo.Bar')
+